Files
OG-Fortnite-Cheat/Fortnite Internal/Drawing/RaaxGUI/RaaxGUI.cpp
T
raax7 fb147b3565 BulletTP!
Features:
- Added BulletTP (pickaxes and non-pojectile weapons)
- Added ability to toggle visible check
- Added ability to toggle sticky aim

Minor Changes:
- Added outline to windows in RaaxGUI
- Made minhook compile with all builds
- Removed unnecessary FPS scale recalculation in Vehicles.cpp
- Added missing functionality for outlined lines on ImGui
- Reworded "ScreeenPositionA" to "ScreenPosition" where there is only 1 screen position
- Changed "PostRender" to "DrawTransition" to match the function it's actually finding
- Changed "ErrorManager::error" to "ErrorManager::ThrowError"
- Added SDKInitializer::InitCalculateShot

Bug-Fixes:
- Fixed text size incorrect on Engine rendering

TO-DO:
- Add more signatures for CalculateShot function offset initialization
2024-03-21 19:59:49 +00:00

627 lines
19 KiB
C++

#include "RaaxGUI.h"
#include "RaaxGUIInput.h"
#include "../../Utilities/Error.h"
// If you are using this library on another project, replace this with your own drawing wrappers (or recreate the ones here)
#include "../Drawing.h"
#include <algorithm>
#include <iomanip>
#include <sstream>
/* CONTEXT FUNCTIONS */
void RaaxGUI::InitContext() {
if (GContext) {
THROW_ERROR(std::string(skCrypt("Context already initialized!")), false);
}
GContext = new RaaxGUIContext();
if (GContext == nullptr) {
THROW_ERROR(std::string(skCrypt("Failed to initialize context!")), true);
}
// Initialize style
GContext->Style.InitDarkStyle();
}
void RaaxGUI::NewFrame() {
RaaxGUIInput::Tick();
// Clear all window seen flags
for (auto Window : GetContext()->RenderQue.Windows) {
if (Window) {
Window->Seen = false;
for (auto Element : Window->Elements) {
Element->Seen = false;
}
Window->ElementsLastFrame = Window->Elements;
Window->Elements.clear();
}
}
}
void RaaxGUI::EndFrame() {
for (int i = 0; i < GetContext()->RenderQue.Windows.size(); i++) {
Window* CurrentWindow = GetContext()->RenderQue.Windows[i];
CurrentWindow->Draw();
}
// Clear all windows that were not seen
for (auto it = GetContext()->RenderQue.Windows.begin(); it != GetContext()->RenderQue.Windows.end();) {
Window* CurrentWindow = *it;
if (CurrentWindow == nullptr) {
it = GetContext()->RenderQue.Windows.erase(it);
continue;
}
if (CurrentWindow->Seen == false) {
it = GetContext()->RenderQue.Windows.erase(it);
delete CurrentWindow;
}
else {
++it;
}
// Loop thru all elements and clear elements that were not seen
for (auto it2 = CurrentWindow->ElementsLastFrame.begin(); it2 != CurrentWindow->ElementsLastFrame.end();) {
Element* CurrentElement = *it2;
if (CurrentElement->Seen == false) {
it2 = CurrentWindow->ElementsLastFrame.erase(it2);
delete CurrentElement;
}
else {
++it2;
}
}
}
}
void RaaxGUI::RaaxGUIContext::MakeWindowTopMost(Window* Window) {
for (int i = 0; i < RenderQue.Windows.size(); i++) {
if (RenderQue.Windows[i] == Window) {
RenderQue.Windows.erase(RenderQue.Windows.begin() + i);
RenderQue.Windows.push_back(Window);
break;
}
}
}
void RaaxGUI::SetNextWindowSize(SDK::FVector2D Size) {
GetContext()->UseNextWindowSize = true;
GetContext()->NextWindowSize = Size;
}
void RaaxGUI::SetNextWindowPos(SDK::FVector2D Pos) {
GetContext()->UseNextWindowPos = true;
GetContext()->NextWindowPos = Pos;
}
RaaxGUI::Window* RaaxGUI::RaaxGUIContext::GetCurrentWindow() {
return CurrentWindow;
}
RaaxGUI::RaaxGUIContext* RaaxGUI::GetContext() {
if (GContext == nullptr) {
THROW_ERROR(std::string(skCrypt("Context not initialized!")), false);
}
return GContext;
}
RaaxGUI::RaaxGUIStyle* RaaxGUI::GetStyle() {
return &GetContext()->Style;
}
/* WINDOW FUNCTIONS */
bool RaaxGUI::BeginWindow(const char* Name, bool* Open, RaaxGUIWindowFlags Flags, SDK::FVector2D InitPosition, SDK::FVector2D InitSize) {
int Id = HashString(Name);
Window* ThisWindow = FindWindowById(Id);
if (ThisWindow == nullptr) {
ThisWindow = RegisterNewWindow(Id);
ThisWindow->ID = Id;
ThisWindow->Size = InitSize;
ThisWindow->Position = InitPosition;
ThisWindow->Name = Name;
}
ThisWindow->Seen = true;
GetContext()->CurrentWindow = ThisWindow;
if (GetContext()->UseNextWindowSize) {
ThisWindow->Size = GetContext()->NextWindowSize;
GetContext()->UseNextWindowSize = false;
}
if (GetContext()->UseNextWindowPos) {
ThisWindow->Position = GetContext()->NextWindowPos;
GetContext()->UseNextWindowPos = false;
}
ThisWindow->CurrentElementPosition = SDK::FVector2D(0, ThisWindow->Style.TitleBarSize.Y);
ThisWindow->Open = *Open;
return ThisWindow->Open;
}
void RaaxGUI::EndWindow() {
GetContext()->CurrentWindow = nullptr;
}
RaaxGUI::Window* RaaxGUI::RegisterNewWindow(int ID) {
Window* NewWindow = new Window();
NewWindow->ID = ID;
GetContext()->RenderQue.Windows.push_back(NewWindow);
return NewWindow;
}
RaaxGUI::Window* RaaxGUI::FindWindowById(int ID) {
for (int i = 0; i < GetContext()->RenderQue.Windows.size(); i++) {
if (GetContext()->RenderQue.Windows[i]->ID == ID) {
return GetContext()->RenderQue.Windows[i];
}
}
return nullptr;
}
void RaaxGUI::Window::Draw() {
if (Open) {
// Draw window
Drawing::FilledRect(Position, Size, Style.BackgroundColor, false);
// Draw title bar
Drawing::FilledRect(Position, SDK::FVector2D(Size.X, Style.TitleBarSize.Y), SDK::FLinearColor(0.2f, 0.2f, 0.2f, 1.f), false);
// Draw border
Drawing::Rect(Position, Size, 1.f, SDK::FLinearColor(0.f, 0.f, 0.f, 1.f), true);
SDK::FVector2D TextPosition = SDK::FVector2D();
switch (Style.TitleBarTextAlignment) {
case TextAlignment::Left:
TextPosition = SDK::FVector2D(Position.X + 5, Position.Y + 5);
break;
case TextAlignment::Center:
TextPosition = SDK::FVector2D(Position.X + (Size.X / 2), Position.Y + 5);
break;
case TextAlignment::Right:
TextPosition = SDK::FVector2D(Position.X + Size.X - 5, Position.Y + 5);
break;
}
Drawing::Text(Name.c_str(), TextPosition, Style.TitleBarTextSize, SDK::FLinearColor(1.f, 1.f, 1.f, 1.f), Style.TitleBarTextAlignment == TextAlignment::Center ? true : false, false, true);
// Draw elements
for (int i = 0; i < Elements.size(); i++) {
Elements[i]->Draw();
}
}
}
void RaaxGUI::Window::OnClickTick(const SDK::FVector2D ClickPosition) {
SDK::FVector2D RelativePosition = ClickPosition - Position;
for (int i = 0; i < Elements.size(); i++) {
Elements[i]->ClickTick(RelativePosition);
}
}
void RaaxGUI::Window::OnClickBegin(const SDK::FVector2D ClickPosition) {
SDK::FVector2D RelativePosition = ClickPosition - Position;
GetContext()->MakeWindowTopMost(this);
for (int i = 0; i < Elements.size(); i++) {
Elements[i]->OnClickBegin(RelativePosition);
}
}
void RaaxGUI::Window::OnClickEnd() {
for (int i = 0; i < Elements.size(); i++) {
Elements[i]->OnClickEnd();
}
}
bool RaaxGUI::Window::ShouldDrag(SDK::FVector2D Position) {
SDK::FVector2D RelativePosition = Position - this->Position;
if (IsInDragBounds(Position)) {
for (int i = 0; i < Elements.size(); i++) {
if (Elements[i]->IsInElementBounds(RelativePosition)) {
return false;
}
}
return true;
}
return false;
}
void RaaxGUI::Window::FixWindowPosition(SDK::FVector2D& Position) {
// Clamp to screen
// Require atleast 10 pixels of the windows drag space to be visible
}
void RaaxGUI::Window::FixWindowSize(SDK::FVector2D& Size) {
// Clamp to minimum size
if (Size.X < MinimumSize.X) {
Size.X = MinimumSize.X;
}
if (Size.Y < MinimumSize.Y) {
Size.Y = MinimumSize.Y;
}
}
bool RaaxGUI::Window::IsInMenuBounds(SDK::FVector2D Position) {
if (Position.X > this->Position.X && Position.X < this->Position.X + this->Size.X) {
if (Position.Y > this->Position.Y && Position.Y < this->Position.Y + this->Size.Y) {
return true;
}
}
return false;
}
bool RaaxGUI::Window::IsInDragBounds(SDK::FVector2D Position) {
return IsInMenuBounds(Position);
}
bool RaaxGUI::Window::IsInResizeBounds(SDK::FVector2D Position) {
// Check if mouse is within 2 pixels of any corner
SDK::FVector2D TopLeft = this->Position;
SDK::FVector2D TopRight = SDK::FVector2D(this->Position.X + this->Size.X, this->Position.Y);
SDK::FVector2D BottomLeft = SDK::FVector2D(this->Position.X, this->Position.Y + this->Size.Y);
SDK::FVector2D BottomRight = SDK::FVector2D(this->Position.X + this->Size.X, this->Position.Y + this->Size.Y);
if (Position.Distance(TopLeft) < 10) {
CurrentResizeDirection = ResizeDirection::TopLeft;
return true;
}
else if (Position.Distance(TopRight) < 10) {
CurrentResizeDirection = ResizeDirection::TopRight;
return true;
}
else if (Position.Distance(BottomLeft) < 10) {
CurrentResizeDirection = ResizeDirection::BottomLeft;
return true;
}
else if (Position.Distance(BottomRight) < 10) {
CurrentResizeDirection = ResizeDirection::BottomRight;
return true;
}
return false;
}
RaaxGUI::ResizeDirection RaaxGUI::Window::GetResizeDirection(SDK::FVector2D Position) {
return CurrentResizeDirection;
}
/* ELEMENT FUNCTIONS */
template<typename ElementType> ElementType* RaaxGUI::RegisterNewElement(int ID, Window* ElementWindow) {
ElementType* NewElement = new ElementType();
NewElement->ID = ID;
NewElement->ParentWindow = ElementWindow;
ElementWindow->Elements.push_back(NewElement);
return NewElement;
}
template<typename ElementType> ElementType* RaaxGUI::FindElementByIdAndWindow(int ID, Window* ElementWindow) {
for (auto& Window : GetContext()->RenderQue.Windows) {
if (Window == ElementWindow) {
for (auto& Element : Window->ElementsLastFrame) {
if (Element->ID == ID) {
return reinterpret_cast<ElementType*>(Element);
}
}
}
}
return nullptr;
}
bool RaaxGUI::Element::IsBeingClicked() {
if (ParentWindow == nullptr) {
return false;
}
return BeingClicked;
}
bool RaaxGUI::Element::IsBeingHovered() {
if (ParentWindow == nullptr) {
return false;
}
return BeingHovered;
}
bool RaaxGUI::Element::Text(const char* RenderText, SDK::FVector2D ScreenPosition, float FontSize, SDK::FLinearColor RenderColor, bool CenteredX, bool CenteredY, bool Outlined) {
if (ParentWindow == nullptr) {
return false;
}
// Get the bounds of the text
SDK::FVector2D TextSize = Drawing::TextSize(RenderText, FontSize);
// Adjust the position for CenteredX and CenteredY
if (CenteredX) {
ScreenPosition.X -= TextSize.X / 2;
}
if (CenteredY) {
ScreenPosition.Y -= TextSize.Y / 2;
}
// Check if both corners of the text are within the bounds of the element
if (ParentWindow->IsInMenuBounds(ScreenPosition) && ParentWindow->IsInMenuBounds(ScreenPosition + TextSize)) {
Drawing::Text(RenderText, ScreenPosition, FontSize, RenderColor, CenteredX, CenteredY, Outlined);
return true;
}
else {
// Attempt to draw the text with 1 less character until it fits
std::string NewText = RenderText;
while (NewText.size() >= 1 && (ParentWindow->IsInMenuBounds(ScreenPosition) && ParentWindow->IsInMenuBounds(ScreenPosition + TextSize)) == false) {
NewText.pop_back();
std::string NewTextTemp = NewText;
NewTextTemp += skCrypt("...");
TextSize = Drawing::TextSize(NewTextTemp.c_str(), FontSize);
}
if (ParentWindow->IsInMenuBounds(ScreenPosition) && ParentWindow->IsInMenuBounds(ScreenPosition + TextSize)) {
NewText += skCrypt("...");
Drawing::Text(NewText.c_str(), ScreenPosition, FontSize, RenderColor, CenteredX, CenteredY, Outlined);
return true;
}
}
return false;
}
bool RaaxGUI::Element::FilledRect(SDK::FVector2D ScreenPosition, SDK::FVector2D ScreenSize, SDK::FLinearColor RenderColor, bool Outlined) {
if (ParentWindow == nullptr) {
return false;
}
// Check if both corners of the rect are within the bounds of the element
if (ParentWindow->IsInMenuBounds(ScreenPosition) && ParentWindow->IsInMenuBounds(ScreenPosition + ScreenSize)) {
Drawing::FilledRect(ScreenPosition, ScreenSize, RenderColor, Outlined);
return true;
}
return false;
}
/* CHECKBOX */
bool RaaxGUI::Checkbox(const char* Name, bool* Value) {
Window* CurrentWindow = GetContext()->GetCurrentWindow();
if (CurrentWindow == nullptr) {
THROW_ERROR(std::string(skCrypt("Attempted to create a GUI element with no current window!")), false);
return false;
}
int Id = HashString(Name);
CheckboxElement* ThisElement = FindElementByIdAndWindow<CheckboxElement>(Id, CurrentWindow);
if (ThisElement == nullptr) {
ThisElement = RegisterNewElement<CheckboxElement>(Id, CurrentWindow);
ThisElement->ID = Id;
ThisElement->Name = Name;
ThisElement->Type = ElementType::Checkbox;
// Checkbo exclusive data
ThisElement->Value = Value;
}
else {
CurrentWindow->Elements.push_back(ThisElement);
}
ThisElement->Seen = true;
if (ThisElement->Type != ElementType::Checkbox) {
THROW_ERROR(std::string(skCrypt("Found another element in the window with the same name! Please keep element and window names unique.")), false);
return false;
}
return *Value;
}
bool RaaxGUI::CheckboxElement::IsInElementBounds(const SDK::FVector2D Position) {
if (Position.X > CheckboxRelativePosition.X && Position.X < CheckboxRelativePosition.X + Style.CheckboxButtonSize.X) {
if (Position.Y > CheckboxRelativePosition.Y && Position.Y < CheckboxRelativePosition.Y + Style.CheckboxButtonSize.Y) {
return true;
}
}
return false;
}
void RaaxGUI::CheckboxElement::ClickTick(SDK::FVector2D Position) {
return;
}
void RaaxGUI::CheckboxElement::OnClickBegin(const SDK::FVector2D ClickPosition) {
if (IsInElementBounds(ClickPosition)) {
BeingClicked = true;
}
}
void RaaxGUI::CheckboxElement::OnClickEnd() {
if (BeingClicked) {
*Value = !*Value;
}
BeingClicked = false;
}
void RaaxGUI::CheckboxElement::Draw() {
WindowStyle& CurrentWindowStyle = ParentWindow->Style;
CheckboxStyle& CurrentElementStyle = Style;
// Draw checkbox
SDK::FVector2D CheckboxPosition = ParentWindow->Position + ParentWindow->CurrentElementPosition;
SDK::FVector2D CheckboxSize = Style.CheckboxButtonSize;
CheckboxPosition = CheckboxPosition + Style.CheckboxPadding;
CheckboxRelativePosition = CheckboxPosition - ParentWindow->Position;
SDK::FLinearColor CurrentCheckboxColor = Style.CheckboxButtonColor;
if (IsBeingClicked()) {
CurrentCheckboxColor = Style.CheckboxButtonClickHeldColor;
}
else if (IsBeingHovered()) {
CurrentCheckboxColor = Style.CheckboxButtonHoverColor;
}
bool DrewCheckbox = FilledRect(CheckboxPosition, CheckboxSize, CurrentCheckboxColor, true);
if (DrewCheckbox && *Value) {
FilledRect(CheckboxPosition + (CheckboxSize / 4.f), CheckboxSize / 2.f, Style.CheckboxEnabledInnerBoxColor, false);
}
// Draw text
SDK::FVector2D TextPosition = CheckboxPosition;
TextPosition.X += CheckboxSize.X + Style.CheckboxTextOffset;
if (DrewCheckbox) Text(Name.c_str(), TextPosition, Style.CheckboxTextSize, Style.CheckboxTextColor, false, false, true);
// CheckboxPadding * 2 because of the padding above and below the checkbox
ParentWindow->CurrentElementPosition.Y += Style.CheckboxButtonSize.Y + (Style.CheckboxPadding.Y * 2);
BoundsPosition = CheckboxPosition;
BoundsSize = CheckboxSize;
}
/* SLIDER */
template<typename SliderValueType> void CreateSliderInternal(const char* Name, SliderValueType* Value, SliderValueType MinValue, SliderValueType MaxValue) {
RaaxGUI::Window* CurrentWindow = RaaxGUI::GetContext()->GetCurrentWindow();
if (CurrentWindow == nullptr) {
THROW_ERROR(std::string(skCrypt("Attempted to create a GUI element with no current window!")), false);
return;
}
int Id = HashString(Name);
RaaxGUI::SliderElement<SliderValueType>* ThisElement = RaaxGUI::FindElementByIdAndWindow<RaaxGUI::SliderElement<SliderValueType>>(Id, CurrentWindow);
if (ThisElement == nullptr) {
ThisElement = RaaxGUI::RegisterNewElement<RaaxGUI::SliderElement<SliderValueType>>(Id, CurrentWindow);
ThisElement->ID = Id;
ThisElement->Name = Name;
ThisElement->Type = RaaxGUI::ElementType::Slider;
// Slider exclusive data
ThisElement->Value = Value;
ThisElement->MinValue = MinValue;
ThisElement->MaxValue = MaxValue;
}
else {
CurrentWindow->Elements.push_back(ThisElement);
}
ThisElement->Seen = true;
if (ThisElement->Type != RaaxGUI::ElementType::Slider) {
THROW_ERROR(std::string(skCrypt("Found another element in the window with the same name! Please keep element and window names unique.")), false);
return;
}
}
void RaaxGUI::SliderFloat(const char* Name, float* Value, float MinValue, float MaxValue) {
CreateSliderInternal<float>(Name, Value, MinValue, MaxValue);
}
void RaaxGUI::SliderInt(const char* Name, int* Value, int MinValue, int MaxValue) {
CreateSliderInternal<int>(Name, Value, MinValue, MaxValue);
}
template<typename SliderValueType> bool RaaxGUI::SliderElement<SliderValueType>::IsInElementBounds(const SDK::FVector2D Position) {
if (Position.X > BoundsPosition.X && Position.X < BoundsPosition.X + BoundsSize.X) {
if (Position.Y > BoundsPosition.Y && Position.Y < BoundsPosition.Y + BoundsSize.Y) {
return true;
}
}
return false;
}
template<typename SliderValueType> void RaaxGUI::SliderElement<SliderValueType>::ClickTick(const SDK::FVector2D ClickPosition) {
if (BeingClicked) {
float CalculatedValue = (ClickPosition.X - BoundsPosition.X) / BoundsSize.X;
CalculatedValue = std::clamp(CalculatedValue, 0.f, 1.f);
*Value = (SliderValueType)((MaxValue - MinValue) * CalculatedValue + MinValue);
}
}
template<typename SliderValueType> void RaaxGUI::SliderElement<SliderValueType>::OnClickBegin(const SDK::FVector2D ClickPosition) {
if (IsInElementBounds(ClickPosition)) {
float CalculatedValue = (ClickPosition.X - BoundsPosition.X) / BoundsSize.X;
CalculatedValue = std::clamp(CalculatedValue, 0.f, 1.f);
*Value = (SliderValueType)((MaxValue - MinValue) * CalculatedValue + MinValue);
BeingClicked = true;
}
}
template<typename SliderValueType> void RaaxGUI::SliderElement<SliderValueType>::OnClickEnd() {
BeingClicked = false;
}
template<typename SliderValueType> void RaaxGUI::SliderElement<SliderValueType>::Draw() {
WindowStyle& CurrentWindowStyle = ParentWindow->Style;
SliderStyle& CurrentElementStyle = Style;
// Setup initial positions and sizes
SDK::FVector2D SliderPosition = ParentWindow->Position + ParentWindow->CurrentElementPosition + Style.SliderPadding;
SDK::FVector2D SliderSize = Style.SliderSize;
// Attempt to draw slider, adjusting size if necessary
bool DrewSlider = false;
for (; DrewSlider == false && SliderSize.X >= 1; SliderSize.X -= 1) {
DrewSlider = FilledRect(SliderPosition, SliderSize, Style.SliderBarColor, true);
}
// Calculate the how far along the slider the value is
float PercentComplete = ((float)*Value - (float)MinValue) / ((float)MaxValue - (float)MinValue);
PercentComplete = std::clamp(PercentComplete, 0.f, 1.f);
// Determine the size of the slider based on the current value
SDK::FVector2D SliderValueSize = SDK::FVector2D(SliderSize.X * PercentComplete, SliderSize.Y);
// Calculate grabber position and size
SDK::FVector2D GrabberPosition = SDK::FVector2D(SliderPosition.X + (SliderSize.X * PercentComplete) - (Style.SliderGrabberWidth / 2), SliderPosition.Y);
SDK::FVector2D GrabberSize = SDK::FVector2D(Style.SliderGrabberWidth, SliderSize.Y);
// Ensure grabber remains within the slider bounds
GrabberPosition.X = std::clamp(GrabberPosition.X, SliderPosition.X, SliderPosition.X + SliderSize.X - GrabberSize.X);
// Formatting the value string with precision
std::stringstream ValueStream;
ValueStream << std::fixed << std::setprecision(2) << *Value;
std::string ValueString = ValueStream.str();
// Calculate text positions
SDK::FVector2D NameTextPosition = SDK::FVector2D(SliderPosition.X + SliderSize.X + Style.SliderNameTextOffset, SliderPosition.Y);
SDK::FVector2D ValueTextSize = Drawing::TextSize(ValueString.c_str(), Style.SliderValueTextSize);
SDK::FVector2D ValueTextPosition = SDK::FVector2D(GrabberPosition.X - (GrabberSize.X / 2), GrabberPosition.Y + Style.SliderValueTextOffset + ValueTextSize.Y);
// Drawing operations
if (DrewSlider) {
FilledRect(SliderPosition, SliderValueSize, Style.SliderValueBarColor, true);
FilledRect(GrabberPosition, GrabberSize, Style.SliderGrabberButtonColor, true);
Text(ValueString.c_str(), ValueTextPosition, Style.SliderValueTextSize, Style.SliderValueTextColor, false, false, true);
}
Text(Name.c_str(), NameTextPosition, Style.SliderNameTextSize, Style.SliderNameTextColor, false, false, true);
// Update the position for the next element
ParentWindow->CurrentElementPosition.Y += SliderSize.Y + Style.SliderPadding.Y + ValueTextSize.Y;
// Set bounds for interaction detection
BoundsPosition = SliderPosition - ParentWindow->Position;
BoundsSize = SliderSize;
}