Mitex's GUI Framework


Introduction!

GUIFramework contains of a LocalScript and Module’s to automate the process of animating buttons,
opening & closing frames and highlights unrestricted custom click actions

An important fact is to give user’s with little to none scripting knowledge
the ability to use this framework regarding the major aspects

Everything is picked up by Tags & Attributes within your own GUI elements

Framework’s couple major aspects:

  • Hover and click animations
  • Sounds whenever interacted with buttons
  • Visibility of GUI containers
  • Handling of frame opening & closing
  • Custom components which execute on button clicks
Difference to other UI frameworks

This framework is purely meant for aspects mentioned above
Any UI element is created by you, and not this framework

Don’t be confused regarding roact or fusion
In this framework we don’t build nor define new UI elements by code
It is no where near to replace/mimic roact nor fusion, those have completely different usage visions

This is mostly an automation framework to handle various tasks

For basic usage;

  • Button animations
  • Frame opening and closing
  • Container visibility

For advanced/custom usage; Yes - You may add script’s

  • Toggleable buttons
  • Custom components that take action on click
    Custom components are optional additions to frame functionality

:exclamation: Custom components are covered in the section: How to use


Who is this meant for? (& benefits)

Developer’s who are looking for a well designed solution which commits to basic but time consuming task(s). Including this to your existing (or new) game is fairly easy as it doesn’t spread around your entire game as much

How the explorer looks after a successful setup

image

Once properly setup - significant time will be saved while adding new buttons & frames

In addition the framework provides basic & advanced functionality as it allows creating your own components. These components will execute when a button with the same name is pressed.

How to use

Demo Video

Installation & Setup

This how-to-do explains the instructions on a new place

1. Create a new place and ungroup the file to its path

2. Creating a left-sided container (01:13)

As we make the left container, an important thing to note is to add the tag Button
into the ImageButton’s

We do this to tell the framework:

  • The button wants to be animated
  • The button wants to open/close a frame

3. Creating frames (01:15)

As you can see: the frame’s are opened and closed - We haven’t edited a single script yet

For a frame to be opened by a button, it is important to name your frame and button equally; otherwise they’re not “linked” to each other

Definiton of "Linked"

With the use of CollectionService our framework is able to see every button with our tag Button
Our LocalScript GraphicalUserInterface then handles the step of trying to open a frame whenever a button is pressed on


Information about close buttons

Both works to close the opened frame:

  • Pressing the same ImageButton
  • Using the close button

When a new frame is loaded in, and a button named Close is added, the framework then automatically applies the button animation and listens for a click, to close the opened frame


4. Creating a right-sided container (00:53)

We repeat the process done as in step 2. but this time our container is on the right side
As our buttons match the frame’s name, each button is responsible to open its linked frame

5. Container Visibility (Fullscreen & Non-Fullscreen) (01:04)

How do we make everything else from the screen be gone when a specific frame is shown?

Short

Frame3
[Tags]: Fullscreen

Left
[Tags]: FullHide
[Attributes]: HidePosition UDmi2 {-0.2, 0},{0.5, 0}

Right
[Tags]: Hide
[Attributes]: HidePosition UDmi2 {1.2, 0},{0.5, 0}

  1. At first we select Frame3 from our GUI storage and add the tag Fullscreen to it
    This frame basically says “Hey! I want to be in fullscreen!” → See how both containers move out

  2. Then we add the tag FullHide to our container Left
    The left container only vanishes when an inserted frame with the tag Fullscreen is loaded in

  3. Container Right also needs to be tagged, but this time with Hide as we want our container to disappear when any frame is loaded in

  4. Lastly, both container’s need an attribute: UDmi2 HidePosition in order to define the container’s move position when being forced to leave the screen

6. Button Interaction Sounds

Provided sounds from creator store can be downloaded here
I do not own these sounds; all credits go to the owner(s)
Sounds.rbxm (2.0 KB)

Make sure to ungroup the model from the .rbxm file above
image

With that done, we have just added interaction sound’s to the framework
:exclamation:As of now; the sound name’s need to be as provided otherwise edit of source code is required!

7. Invite Button: Adding a component (PreClone)

We have already created a button named “Invite”, but we didn’t add a frame
as none pre-made frame should be opened, but a specific code run when pressing
that invite button. Our goal is to open the roblox’s invite prompt included in SocialService

Commented snippet of such component
local SocialService = game:GetService("SocialService")

return function(self)
	-- check if the player can invites
	local success, result = pcall(SocialService.CanSendGameInviteAsync, SocialService, self.player)

	if (result) then
		-- if a frame is opened; close it
		if #self.insertedGui:GetChildren() > 0 then
			self:Insert(self.insertedGui:GetChildren()[1].Name)
		end
		
		-- prompting roblox's invite frame
		SocialService:PromptGameInvite(self.player)
	end
	
	-- returning false instead of true
	-- to stop further code from running
	return false
end

image


PreClone & PostClone (Custom Components)

What are, when and where do both take part?

Let custom actions happen when a button is clicked - adding new behaviours!

When your button is pressed, the framework looks for a components name which equals to the buttons name; if found → the function returned by the component is called

Two folder’s can be found parented to HandlerGui; there you’ll have to add your ModuleScripts
More information is given further down this section

Explorer image with both folders

image

When adding a component to PostClone folder,
the module will run after the clone of the frame but before parenting it!

Talking about PreClone

When adding a component to PreClone folder
the module will run before the clone of the frame.

Why’s it useful?

When the component returns false - the code to run the cloning will be canceled meaning it won’t try handling a frame.

:exclamation:An example of usage is covered in [Installation & Setup]


API Documentaton

As previously said, this framework uses module’s
Made with 2 modules, with both serving their own purpose

Covered in this documentation HandlerGUI, ButtonAnimation and GraphicalUserInterface

GraphicalUserInterface (LocalScript)

Everything explained in the code - if something is unclear let me know

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local CollectionService = game:GetService("CollectionService")

local player = game:GetService("Players").LocalPlayer

player.PlayerGui:WaitForChild("Modules")

-- requiring both modules
local ButtonAnimation = require(player.PlayerGui.Modules.ButtonAnimation)
local HandlerGUI = require(player.PlayerGui.Modules.HandlerGUI)

local AnimationClassBlacklist = {"ImageLabel"}

function ButtonAdded(button)
	-- ButtonAnimation is called to have our button animated
	ButtonAnimation(button)
	
	if table.find(AnimationClassBlacklist, button.ClassName) then
		return
	end
	
	-- calls 'HandlerGUI' with 'button.Name' which is the frame we want to open/close
	-- inside the module: a frame's name equal to the button name which is clicked is opened/closed 
	-- further details in the 'HandlerGUI' documentation: HandlerGUI:Insert(frameName: string, ... : any): ()
	
	button.MouseButton1Up:Connect(function()
		HandlerGUI(button.Name)
	end)
end

for _, button: ImageButton in next, CollectionService:GetTagged("Button") do	
	if not button:IsDescendantOf(ReplicatedStorage.GUI) then -- skipping buttons that are inside our GUI storage 
		
		-- calls 'ButtonAdded' for every already existing button with tag 'Button'
		ButtonAdded(button)
	end
end

-- call 'ButtonAdded' whenever a new button with tag 'Button' is added
CollectionService:GetInstanceAddedSignal("Button"):Connect(ButtonAdded)
HandlerGUI (Module)

An example of usage can be found in the provided GraphicalUserInterface LocalScript
When trying to open a frame from outside the module’s we’ll have to do following:
image

Module Main is the worker to handle this when HandlerGUI

Main is the function that listens for table calls __call = require(script.Main)
Which if no debounce is active, the provided frame is handled

More on the debounce

The time which a debounce is present for, is the time a frame takes to open
Time can be adjusted in the config file defaultSpeed. It can be acquired within the module as self.defaultSpeed


HandlerGUI functions:

HandlerGUI:Blur(override: boolean?): ()

Function updates the blur state
When override is given, the blur’s state is forcely set


HandlerGUI:ClearInserted(): ()

Calls :Destroy() on every instance parented to insertedGui


HandlerGUI:CloseButton(frame: GuiObject): ()

Check if a close button inside frame is given

If found:

  • An animation is added (By giving the button a tag Button)
  • MouseButton1Up is being connected to close it’s frame when pressed

HandlerGUI:FindInsertedFolder(): (Folder?)

On Module require, this function’s looks for your InsertedGui
Which is in the module itself is referenced to as self.insertedGui


HandlerGUI:Hide(): ()

When called, updates the position of container(s) (Installation & Setup → 5. Container Visibility)
By going through the tags Hide & FullHide

If container’s should move out or in is defined by the amount of children inside self.insertedGui


HandlerGUI:Insert(frameName: string, ... : any): ()

This handles PreClone & PostClone; More on that in [How to use] → [PreClone & PostClone (Custom Components)]

If called with frameName already being inside of self.insertedGui, it forces the opened to close

If frameName is not a member of your GUI storage, the function simply returns nil
Happens after PreClone

When the frame is found; it’ll clone and PostClone runs right after
followed by self:OpenFrame(frame, ...) & self:CloseButton(frame)


HandlerGUI:OpenFrame(frame: GuiObject, ... : any): ()

Just as the function name says, it opens the frame given
It’s the last function to run when opening a frame

Calling it directly might cause issues; As it force opens the given frame without any checks
Please consider using HandlerGUI:Insert(frameName: string, ... : any): () for external usage


HandlerGUI:PlaySound(soundName: string): ()

Looks for a matching sound in SoundService
It clones the sound and applies .PlayOnRemove = true
It’s parented to the workspace and immediately scheduled through Debris

This function is used to play sound’s;

  • Button Hover
  • Button Click

HandlerGUI:TweenFOV(fieldOfView: number, direction: string?, tweenTime: number?): ()
  • fieldOfView: CurrentCamera FieldOfView is tweened to fieldOfView

  • direction: Used for Enum.EasingDirection; If direction is given, parameter will be used for its EasingDirection else Enum.EasingDirection.Out is set

  • tweenTime: the time it takes for the fov tween to complete, if not set → self.Config.timeFOV



ButtonAnimation (Module)
Calling ButtonAnimation

In the provided LocalScript GraphicalUserInterface we see that ButtonAnimation is also used by directly calling the modules table
ButtonAnimation(listen: {Instance}, change: {Instance}?)

What is a worker & when is it created

A new worker is created when calling ButtonAnimation → Every worker is unique
It handles the connection part for it’s applied instance(s) of parameter listen

  • MouseButton1Down
  • MouseButton1Up
  • MouseEnter
  • MouseLeave

What does ButtonAnimation return?

It returns function’s, tables, configuration and it’s asigned worker
Most part’s returned can be ignored as it’d be a special usecase
image

Configuration of a button

What’s more important is being able to change an instances configuration

  • Color = Color3
  • ScaleFactor = number
-- example of applying an animation to a button
local animation = ButtonAnimation(script.Parent)
Setting a configuration

animation.Config.SetInstanceConfig(button: ImageButton, {Color = Color3, ScaleFactor = number})

This method overwrites the current instance configuration


Updating a configuration

animation.Config.UpdateInstanceConfig(button: ImageButton, {Color = Color3?, ScaleFactor = number?})

  1. Gets current configuration inside the config module
  2. config parameter then overwrites the old keys given with the our parameter config
  3. New configuration is returned

Getting a configuration

animation.Config.GetInstanceConfig(button: ImageButton)

Current configuration of button is returned


An example of changing an instances configuration would
become handy → covered in Installation & Setup


Definition of parameters
listen
  • collection of instances which are being connected to
  • single instance which is being connected to

A worker is applied to each instance given
More on worker → ButtonAnimation (Module) → Calling ButtonAnimation

If you want multiple buttons to animate whenever any of those are interacted with:

ButtonAnimation({button1, button2, button3})

If you want only a single button to animate:

ButtonAnimation(button)

change

If you want a single button to animate multiple instances simultaneously:
ButtonAnimation(button1, {button2, button3, button4})

If you want a single button to animate another button
ButtonAnimation(button1, button2)


If change is not given, every instance of listen becomes the change argument



In the future
  • External insertion of PreClone & PostClone
  • More config settings
  • Source code polishing
    and more

Post is soon to be continued with more information covering:

  • Toggleable buttons shown in the old post (Updating an instances config - ButtonAnimation)
  • PostClone (PreClone is covered)

Old post

Expand
What is this framework? - As the title says it's a GUI Framework

An easy to use framework, aiming to be used by developer’s with and ‘without’ scripting experience!
Accomplished by using Tags & Attributes - suitable for everyone

:star: Handles opening & closing frames with ease! :star:
Click for test place


GUI placeholders & explorer - reference throughout this post


Features

Button Sounds

Simply create sounds in SoundService set your id and ready!
:exclamation:Note: that those name’s shown need to be matching

image


Button Container Hiding

Setting Container Tags & Attributes

There’s 2 types of container hiding: fullscreen & non-fullscreen

1. To apply fullscreen:

  • Tag your frame with Fullscreen which wants to be in fullscreen!
  • Tag your container(s) with FullHide which will only vanish
    when a frame with tag Fullscreen is loaded in!

2. To apply non-fullscreen

  • Tag your container(s) with Hide to disappear when ANY frame is loaded in

3. Hide Position:

As seen in Images: Explorer & Properties an attribute is set

  • Type: UDmi2
  • Attribute name HidePosition
  • Defines where container(s) should move when a frame is inserted
Images: Explorer & Properties





Button Animation

For a button animation you would have to set a tag Button in your button!

Toggleable Buttons

The ButtonAnimation allows for color switching, but needs some extra code

Code
local player = game:GetService("Players").LocalPlayer
player.PlayerGui:WaitForChild("Modules")

local ButtonAnimation = require(player.PlayerGui.Modules.ButtonAnimation)
local animation = ButtonAnimation(script.Parent)

if player:GetAttribute("Custom1") == nil then
	player:SetAttribute("Custom1", false)
end

function Update()
	local config = animation.Config.GetInstanceConfig(script.Parent)
	
	config.Color = player:GetAttribute("Custom1")
		and Color3.fromRGB(117, 255, 96)
		or Color3.fromRGB(255, 69, 72)

	animation.Config.SetInstanceConfig(script.Parent, config)
	script.Parent.ImageColor3 = animation.Darken(config.Color, 1.25)
end

player:GetAttributeChangedSignal("Custom1"):Connect(Update)
Update()

script.Parent.ImageColor3 = player:GetAttribute("Custom1")
	and Color3.fromRGB(81, 255, 69)
	or Color3.fromRGB(255, 69, 72)

Reason of implementation:
When a color is switched while hovering, the color would be overwritten with its old color when the hover is ended.

A small example script is provided to prevent this issue from happening
:exclamation:Note: Do not set Button as a tag on the button when using the script, as it would probably cause unknown issues


Automatic GUI Opening

When clicking a button with Button as a tag → clones & opens the frame with an equal name from your GUI folder.

Note: Trying to open an already opened frame will result in an immediate close of it


Automatic Close Button Handling

If you have a close button, name it Close
The framework will handle the MouseClick

:exclamation:Note: Do not set Button as a tag on the close button as its animation will be set automatically!


Programmable Button Actions

PreClone & PostClone

Let actions happen when a button is clicked!

PostClone

When adding a component to PostClone folder
the module that matches with the button’s name
which as been clicked will run after the clone
of the frame but before parenting it!

Meaning you can change the frame however you want!

Example with attributes

ModuleScript Setup

ModuleScript Setup

return function(self, frame, attribute)
	frame:SetAttribute("TestAttribute", attribute)
end

LocalScript Setup

image

LocalScript [Button]:

local ReplicatedStorage = game:GetService("ReplicatedStorage")

local player = game:GetService("Players").LocalPlayer
player.PlayerGui:WaitForChild("Modules")

local HandlerGUI = require(player.PlayerGui.Modules.HandlerGUI)
local ButtonAnimation = require(player.PlayerGui.Modules.ButtonAnimation)
ButtonAnimation(script.Parent)

script.Parent.MouseButton1Up:Connect(function()
	HandlerGUI(script.Parent.Name, "Hello World")
end)

LocalScript [Frame]:

script.Parent.TextLabel.Text = `"{script.Parent:GetAttribute("TestAttribute")}"`

Result:
image

Realworld usecase with attributes:

Let’s say your first frame has a grid menu with buttons
6 Buttons - each button has its own unique number (1 to 6)

When clicked - another frame should be opened but with information
about the interaction that happened on the first frame

Now the localscript from above becomes handy
as it passes information to second frame before its parented.


PreClone

When adding a component to PreClone folder
the module that matches with the button’s name
which as been clicked will run before the clone.

Why’s it useful?

When returning false - the code to run the cloning will be canceled meaning it won’t try opening a frame.

An example with an invite prompt is shown in the video at the top of this post!

Invite Prompt

image

local SocialService = game:GetService("SocialService")

return function(self)
	local success, result = pcall(SocialService.CanSendGameInviteAsync, SocialService, self.player)

	if (result) then
		if #self.insertedGui:GetChildren() > 0 then
			self.Components:Insert(self.insertedGui:GetChildren()[1].Name)
		end

		SocialService:PromptGameInvite(self.player)
	end

	return false
end

Config

The HandlerGUI module also comes with a config file - pretty self explaining


For purchases: Direct Message or mitex7183
Price at 30K

Made by @mitex7183

END OF OLD POST



Post will most likely be adjusted over the time

Last updated: 2024-06-13T18:08:00Z


For purchases: Direct Message or mitex7183

About feedback and suggestions

For constructive feedback and suggestions write on this post
With a clearer vision of this framework, it is highly appreciated to help improve it along the way
Let me know if any aspects and or features are unclear - I’ll adapt this post

Thanks!

Price at 12.5K

I understand many people in this post are upset/making fun of the high price
However; it is my project and I am the only to decide for what price I want to sell my work for.
Justified or not is each persons opinion
This framework is aimed to be an easy to follow addition to games

Made by @mitex7183


Post will most likely be adjusted over the time

Last updated: 2024-06-15T21:22:00Z

5 Likes

No offense but for 30k rbx I could purchase TPGI

9 Likes

I do agree, not to be rude but I feel like 30K robux could just go to making someone making the full UI for a game with images and all (well maybe a more simple one). Or spend like 5K robux and get UI just like this

Other than that pretty cool

1 Like

Hey! I’d just like to point out that the UI elements shown in the video are pure placeholders to show what’s possible. :saluting_face:

As said already, it’s a framework working together with ‘any’ UI - the goal is to wrap the entire game’s GUI; buttons & frames with this framework to increase workflow and taking care of the GUI handling.

The point is that the GUI design shown has nothing to do with the pricing or GUI layout, purely the framework matters. :grinning:

but like all the features could still be gotten for less, just saying.
Otherwise again nice just expensive

30k for what? Theres no way a bunch of MouseButton1Click events cost 30k.

3 Likes

I understand what you’re trying to say, but the idea of this isn’t really appealing. This is for a few reasons:

  1. With such limited documentation, you can’t really understand this without reading the source, which would restrict the people this would be beneficial to.
  2. The 30k price point is a quite premium price point for what you are realistically getting. I think the only people that purchasing this would make sense for are people with money that want a simple solution for a project. Like what @FroDev1002 said, it would be more reasonable for them to commission someone to do this for a better price, which would probably be better suited because it’s specialized for them.
  3. The types of games that would ever need a UI framework would probably rather use an object oriented version because it makes more sense for these type of UIs.

I don’t believe that talking about something like this and not providing constructive feedback is helpful for anyone, so here are some potential solutions for you:

  1. Add an interface for controlling the UI with scripts.
  2. Add more features in general. Like check boxes, sliders, or toggles.
  3. Add a notification UI as well because 30k is a lot for what you are getting. (based on the demos you provided and the limited documentation)
  4. Add a tutorial and extend the documentation so that it describes how it works or how to use it in depth.

Overall, I think this is cool, but I don’t think there is really a market for paid UI frameworks that can’t be interfaced with scripts. Maybe I’ll end up eating my words about this, but regardless, good luck with your project. :man_in_motorized_wheelchair:

4 Likes

Thanks a lot for the great feedback!
I’ll edit this post in the future to make it more understandable on what the features do and what I’m trying to achieve with this framework :+1:

More features will be added as well

I can buy every single game pass I ever wanted in various games for 30k robux. This is a little too expensive. Also how is this better than already good known and totally free fusion or react?

I see how confusing this post it. I’m currently rewritting the entire post

My current goal is to explain the main usage of this
It is not similar to fusion nor react; It’s an automatic gui handler for games which focuses on animations and visibility of frames & containers - defined by tags and attributes,

For basic usage this framework would require 0 scripting as everything is handled automatically.
You’d create the buttons on your own and tag them; the framework for example would then apply button animations and perform frame opening and closing depending on the buttons name

But as I said, I’m currently rewriting this post :+1:

good luck on that test place mobile executors still a thing (he doesnt know whats coming (saveinstance) )

1 Like

$5500 for this is wild lol, especially for something that can be made in like a week
i like the concept and idea though

1 Like

I got bored and recreated the entirely of this in a few hours.

Not worth it at all.

1 Like

A week? You are overestimating it. Max it’d take like 2-3 hours if I got into the flow of it without any distractions.

I don’t see anything perplexing that can justify the price tag of this framework. Perhaps you may enlighten us a little more?

What is it exactly? What’s the benefit over other free OSS (Roact, VideUI, Fusion)? Does the quality meet the expectations for such a price?

I don’t usually comment on these, but this is scammy behavior. For anyone who has not earned Robux, this plugin costs £120/$150 (Originally £250/$316)

You’ve also not demonstrated any code for the ‘framework’ you made, and have no documentation. There’s nothing to say it’s lightweight or ‘professional’ either.

And everything you’ve shown can be replicated with an hours worth of code. Pretty sure it goes against the rules of the category.

1 Like

Hey, later today the documention and code example’s will be added as haven’t gotten enough time to fully finish.

I understand your frustration, like already said in the post, API usage and examples will be covered very soon, thanks :+1:

This is very true, from what I can see the framework gives hardly any value for the price tag

And as this comment has said this could be recreated very quickly with little to no work.
Not to be rude but seriously, what value does this product give?

You could hire someone off fiver for 5 dollars to make something infinitely better then this.

Actually I could make this myself in less then 2 hours.

Definitely going to report this to support, you might actually get a buyer or something :skull::skull::skull:

1 Like

How does this make sense?
You probably haven’t paid any attention whatsoever.

Your feedback is 0 helpful, simply saying “Oh! Someone else can make it for cheaper let me report this post, is just not it”

Should’ve taken @Witchrie as an example and some others,
as I received feedback which I can work on :+1:

I’m constantly adjusting and adding stuff to this post, as there as been a lot of confusion, thanks though