Skip to content
This repository has been archived by the owner on Oct 11, 2024. It is now read-only.

Commit

Permalink
Merge pull request #76 from lucoiso/development
Browse files Browse the repository at this point in the history
HttpGPT v1.5.5
  • Loading branch information
lucoiso authored Aug 15, 2023
2 parents 45947b4 + 205a3f7 commit 334ec35
Show file tree
Hide file tree
Showing 20 changed files with 1,302 additions and 1,150 deletions.
4 changes: 2 additions & 2 deletions HttpGPT.uplugin
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"FileVersion": 3,
"Version": 17,
"VersionName": "1.5.4",
"Version": 18,
"VersionName": "1.5.5",
"FriendlyName": "HttpGPT - GPT Integration",
"Description": "HttpGPT is an Unreal Engine plugin that facilitates integration with OpenAI's GPT based services (ChatGPT and DALL-E) through asynchronous REST requests, making it easy for developers to communicate with these services. HttpGPT also includes new Editor Tools to integrate Chat GPT and DALL-E image generation directly in the Engine.",
"Category": "Game Features",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
// Author: Lucas Vilas-Boas
// Year: 2023
// Repo: https://github.com/lucoiso/UEHttpGPT

#include "HttpGPTMessagingHandler.h"
#include <HttpGPTInternalFuncs.h>
#include <Widgets/Layout/SScrollBox.h>

#ifdef UE_INLINE_GENERATED_CPP_BY_NAME
#include UE_INLINE_GENERATED_CPP_BY_NAME(HttpGPTMessagingHandler)
#endif

UHttpGPTMessagingHandler::UHttpGPTMessagingHandler(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer)
{
}

void UHttpGPTMessagingHandler::RequestSent()
{
OnMessageContentUpdated.ExecuteIfBound("Waiting for response...");
}

void UHttpGPTMessagingHandler::RequestFailed()
{
OnMessageContentUpdated.ExecuteIfBound("Request Failed.\nPlease check the logs. (Enable internal logs in Project Settings -> Plugins -> HttpGPT).");
Destroy();
}

void UHttpGPTMessagingHandler::ProcessUpdated(const FHttpGPTChatResponse& Response)
{
ProcessResponse(Response);
}

void UHttpGPTMessagingHandler::ProcessCompleted(const FHttpGPTChatResponse& Response)
{
ProcessResponse(Response);
Destroy();
}

void UHttpGPTMessagingHandler::ProcessResponse(const FHttpGPTChatResponse& Response)
{
bool bScrollToEnd = false;
if (ScrollBoxReference.IsValid())
{
bScrollToEnd = FMath::Abs(ScrollBoxReference->GetScrollOffsetOfEnd() - ScrollBoxReference->GetScrollOffset()) <= 8.f;
}

if (!Response.bSuccess)
{
const FStringFormatOrderedArguments Arguments_ErrorDetails{
FString("Request Failed."),
FString("Please check the logs. (Enable internal logs in Project Settings -> Plugins -> HttpGPT)."),
FString("Error Details: "),
FString("\tError Code: ") + Response.Error.Code.ToString(),
FString("\tError Type: ") + Response.Error.Type.ToString(),
FString("\tError Message: ") + Response.Error.Message
};

OnMessageContentUpdated.ExecuteIfBound(FString::Format(TEXT("{0}\n{1}\n\n{2}\n{3}\n{4}\n{5}"), Arguments_ErrorDetails));
}
else if (Response.bSuccess && !HttpGPT::Internal::HasEmptyParam(Response.Choices))
{
OnMessageContentUpdated.ExecuteIfBound(Response.Choices[0].Message.Content);
}
else
{
return;
}

if (ScrollBoxReference.IsValid() && bScrollToEnd)
{
ScrollBoxReference->ScrollToEnd();
}
}

void UHttpGPTMessagingHandler::Destroy()
{
ClearFlags(RF_Standalone);

#if ENGINE_MAJOR_VERSION >= 5
MarkAsGarbage();
#else
MarkPendingKill();
#endif
}
41 changes: 41 additions & 0 deletions Source/HttpGPTEditorModule/Private/Chat/HttpGPTMessagingHandler.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// Author: Lucas Vilas-Boas
// Year: 2023
// Repo: https://github.com/lucoiso/UEHttpGPT

#pragma once

#include <CoreMinimal.h>
#include <UObject/Object.h>
#include "HttpGPTMessagingHandler.generated.h"

DECLARE_DELEGATE_OneParam(FMessageContentUpdated, FString);

UCLASS(MinimalAPI, NotBlueprintable, NotPlaceable, Category = "Implementation")
class UHttpGPTMessagingHandler : public UObject
{
GENERATED_BODY()

public:
explicit UHttpGPTMessagingHandler(const FObjectInitializer& ObjectInitializer = FObjectInitializer::Get());

FMessageContentUpdated OnMessageContentUpdated;

UFUNCTION()
void RequestSent();

UFUNCTION()
void RequestFailed();

UFUNCTION()
void ProcessUpdated(const FHttpGPTChatResponse& Response);

UFUNCTION()
void ProcessCompleted(const FHttpGPTChatResponse& Response);

TSharedPtr<class SScrollBox> ScrollBoxReference;

void Destroy();

private:
void ProcessResponse(const FHttpGPTChatResponse& Response);
};
112 changes: 112 additions & 0 deletions Source/HttpGPTEditorModule/Private/Chat/SHttpGPTChatItem.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
// Author: Lucas Vilas-Boas
// Year: 2023
// Repo: https://github.com/lucoiso/UEHttpGPT

#include "SHttpGPTChatItem.h"
#include "HttpGPTMessagingHandler.h"
#include <Widgets/Text/SMultiLineEditableText.h>

void SHttpGPTChatItem::Construct(const FArguments& InArgs)
{
MessageRole = InArgs._MessageRole;
InputText = InArgs._InputText;

if (MessageRole == EHttpGPTChatRole::Assistant)
{
MessagingHandlerObject = NewObject<UHttpGPTMessagingHandler>();
MessagingHandlerObject->SetFlags(RF_Standalone);
MessagingHandlerObject->ScrollBoxReference = InArgs._ScrollBox;

MessagingHandlerObject->OnMessageContentUpdated.BindLambda(
[this](FString Content)
{
if (!Message.IsValid())
{
return;
}

#if ENGINE_MAJOR_VERSION > 5 || (ENGINE_MAJOR_VERSION == 5 && ENGINE_MINOR_VERSION >= 1)
const FTextSelection SelectedText = Message->GetSelection();
Message->SetText(FText::FromString(Content));
Message->SelectText(SelectedText.GetBeginning(), SelectedText.GetEnd());
#else
Message->SetText(FText::FromString(Content));
#endif
}
);
}

ChildSlot
[
ConstructContent()
];
}

TSharedRef<SWidget> SHttpGPTChatItem::ConstructContent()
{
constexpr float SlotPadding = 4.0f;

FText RoleText = FText::FromString(TEXT("Undefined:"));
FMargin BoxMargin(SlotPadding);

if (MessageRole == EHttpGPTChatRole::User)
{
RoleText = FText::FromString(TEXT("User:"));
BoxMargin = FMargin(SlotPadding, SlotPadding, SlotPadding * 16.f, SlotPadding);
}
else if (MessageRole == EHttpGPTChatRole::Assistant)
{
RoleText = FText::FromString(TEXT("Assistant:"));
BoxMargin = FMargin(SlotPadding * 16.f, SlotPadding, SlotPadding, SlotPadding);
}
else if (MessageRole == EHttpGPTChatRole::System)
{
RoleText = FText::FromString(TEXT("System:"));
BoxMargin = FMargin(SlotPadding * 8.f, SlotPadding);
}

const FMargin MessageMargin(SlotPadding * 4.f, SlotPadding, SlotPadding, SlotPadding);

#if ENGINE_MAJOR_VERSION < 5
using FAppStyle = FEditorStyle;
#endif

return SNew(SBox)
.Padding(BoxMargin)
[
SNew(SBorder)
.BorderImage(FAppStyle::Get().GetBrush("Menu.Background"))
[
SNew(SVerticalBox)
+ SVerticalBox::Slot()
.Padding(SlotPadding)
.AutoHeight()
[
SAssignNew(Role, STextBlock)
.Font(FCoreStyle::GetDefaultFontStyle("Bold", 10))
.Text(RoleText)
]
+ SVerticalBox::Slot()
.Padding(MessageMargin)
.FillHeight(1.f)
[
SAssignNew(Message, SMultiLineEditableText)
.AllowMultiLine(true)
.AutoWrapText(true)
.IsReadOnly(true)
.AllowContextMenu(true)
.Text(FText::FromString(InputText))
]
]
];
}

FString SHttpGPTChatItem::GetRoleText() const
{
return Role.IsValid() ? Role->GetText().ToString() : FString();
}

FString SHttpGPTChatItem::GetMessageText() const
{
return Message.IsValid() ? Message->GetText().ToString() : FString();
}
39 changes: 39 additions & 0 deletions Source/HttpGPTEditorModule/Private/Chat/SHttpGPTChatItem.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// Author: Lucas Vilas-Boas
// Year: 2023
// Repo: https://github.com/lucoiso/UEHttpGPT

#pragma once

#include <CoreMinimal.h>
#include <Widgets/SCompoundWidget.h>
#include "Structures/HttpGPTChatTypes.h"

class SHttpGPTChatItem final : public SCompoundWidget
{
public:
SLATE_BEGIN_ARGS(SHttpGPTChatItem) : _MessageRole(), _InputText(), _ScrollBox()
{
}
SLATE_ARGUMENT(EHttpGPTChatRole, MessageRole)
SLATE_ARGUMENT(FString, InputText)
SLATE_ARGUMENT(TSharedPtr<class SScrollBox>, ScrollBox)
SLATE_END_ARGS()

void Construct(const FArguments& InArgs);

FString GetRoleText() const;
FString GetMessageText() const;

TWeakObjectPtr<class UHttpGPTMessagingHandler> MessagingHandlerObject;

private:
TSharedRef<SWidget> ConstructContent();

EHttpGPTChatRole MessageRole;
FString InputText;

TSharedPtr<class STextBlock> Role;
TSharedPtr<class SMultiLineEditableText> Message;
};

typedef TSharedPtr<SHttpGPTChatItem> SHttpGPTChatItemPtr;
Loading

0 comments on commit 334ec35

Please sign in to comment.