Skip to content

Commit

Permalink
Merge pull request #2 from ImAvafe/dev
Browse files Browse the repository at this point in the history
Dev
  • Loading branch information
ImAvafe authored Dec 6, 2023
2 parents 488e73e + f9149bc commit 8a95fb1
Show file tree
Hide file tree
Showing 19 changed files with 510 additions and 177 deletions.
Binary file added .moonwave/static/img/FullCover.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added .moonwave/static/img/SocialIcon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified DemoPlace.rbxl
Binary file not shown.
20 changes: 12 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,26 +7,30 @@
</p>

<p align="center">
A modern, customizable hotbar for Roblox
A modern, flexible hotbar for Roblox
</p>

<p align="center">
<img title="PC, Mobile, Console & VR" alt="Platforms" src="https://img.shields.io/badge/compatibility-💻_📱_🎮_🥽-2ea44f"></img>
<img title="MIT licensed" alt="License" src="https://img.shields.io/github/license/ImAvafe/NeoHotbar"></img>
</p>

## Installation 📦
---

*NeoHotbar is not ready to install! The following instructions are <u>placeholder!</u>*
## [Installation 📦](https://avafe.me/NeoHotbar/docs/intro/#installation)

For easy installation, insert [NeoHotbar](https://example.com) from the Toolbox. **UPDATE MEE**
## Features

For Rojo / advanced users, read the [installation docs](https://avafe.me/NeoHotbar/docs/intro#installation).
- Modern design
- Proper mobile, console and VR support
- Full UI overriding
- Custom buttons
- Functional properties

## Documentation 📄
## [Documentation 📄](https://avafe.me/NeoHotbar/docs/intro)

For info on customization, API and more, visit the [documentation site](https://avafe.me/NeoHotbar/docs/customization).
For info on customization, API and more, visit the [documentation site](https://avafe.me/NeoHotbar/docs/intro).

## Live Demo
## [Live Demo 🎮](https://roblox.com/games/12259231211)

A live testing place is available at [NeoHotbar Demo](https://roblox.com/games/12259231211).
47 changes: 22 additions & 25 deletions docs/customization.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,39 +4,36 @@ sidebar_position: 2

# Customization

## Custom UI

NeoHotbar's UI is fully overridable, so you can customize it however you like! You can also plug into reactive properties like `Equipped`.

*Behind the scenes, this uses Fusion's magical instance hydration!*

### Modifying
## Custom buttons

1. Copy over the default UI to use as a template. The default UI can be found in `NeoHotbar/UI/DefaultInstances`.
2. Piece the components together for live preview.
3. Modify all you like, you have full control!
You can add your own custom buttons to NeoHotbar, like to open a backpack for example!

### Applying
1. First, find an image to use for the button's icon.
2. Next, let's add the button to NeoHotbar. We'll use the image's asset ID and a callback function to tell NeoHotbar what to do when it's clicked.

1. Break your UI apart again and put it into a folder.
2. Call `:OverrideGui()` on NeoHotbar and tell it to use your folder.
```
local NeoHotbar = require(path.to.NeoHotbar)
## Custom buttons
NeoHotbar:AddCustomButton("rbxassetid://0", function()
print('Button was clicked!')
end)
```
3. You're done! You can hook this button up to whatever you want in your game.
You can add your own custom buttons to NeoHotbar, like for opening a backpack, or a pet inventory! They'll be locked to the left, and look extra special compared to the other items.
## Custom UI
First, find an image you really like. I'll just use this "add" icon for the tutorial. Copy its Asset ID.
NeoHotbar's UI is fully overridable, so you can customize it however you like! You can also plug into dynamic attributes like `Equipped` to have your UI react to changes.
*image here*
1. Copy over the default UI to use as a template. The folder can be found in `NeoHotbar/DefaultInstances`.
2. Modify all you like, you have full control!
3. Call [:OverrideGui()](/api/NeoHotbar#OverrideGui) on NeoHotbar, passing your folder as an argument.
Next, let's add the button to NeoHotbar. We'll use the image ID, and a callback function to tell NeoHotbar what to do when it's clicked.
```
local NeoHotbar = require(path.to.NeoHotbar)
## Properties
NeoHotbar:AddCustomButton("rbxassetid://0w0", function()
print('Button was clicked!')
end)
```
You might want to change simpler things, like temporarily hiding the hotbar or locking tool reordering. You can set those properties with the functions listed here:
You're done! You can hook this button up to whatever you want in your game!
- [SetEnabled](/api/NeoHotbar#SetEnabled)
- [SetManagementEnabled](/api/NeoHotbar#SetManagementEnabled)
- [SetToolTipsEnabled](/api/NeoHotbar#SetToolTipsEnabled)
- [SetContextMenuEnabled](/api/NeoHotbar#SetContextMenuEnabled)
5 changes: 3 additions & 2 deletions docs/intro.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ It follows standard Roblox conventions, using the `Tool` object and its associat
### Roblox Studio

1. Get [NeoHotbar](https://example.com) from the toolbox.
2. Place NeoHotbar into `StarterPlayer/StarterPlayerScripts`
2. Place the loader into `StarterPlayer/StarterPlayerScripts`
3. *If you want to use the API, you can take the module out of the loader script.*

### Rojo + Wally

Expand All @@ -24,4 +25,4 @@ It follows standard Roblox conventions, using the `Tool` object and its associat

---

That's all you actually need to do to use NeoHotbar! Now you can leave it as-is or get into *[customization](/docs/customization).*
That's all you need to do to use NeoHotbar! Now you can leave it as-is or get into *[customization](/docs/customization).*
25 changes: 8 additions & 17 deletions moonwave.toml
Original file line number Diff line number Diff line change
@@ -1,33 +1,24 @@
[docusaurus]
title = "NeoHotbar"
tagline = "A modern, flexible hotbar for Roblox"
url = "https://avafe.me"
tagline = "A modern, customizable hotbar for Roblox"
favicon = "/img/favicon.svg"

[home]
enabled = true

[[home.features]]
title = "Easy to Use"
description = "Getting started with NeoHotbar is easy, and customization is too."
description = "Getting started with NeoHotbar is easy and customization is too."

[[home.features]]
title = "Customization"
description = "NeoHotbar features full GUI overriding, custom buttons and more. Make your hotbar for you."
title = "Customizable"
description = "NeoHotbar features custom buttons, full UI overriding and more."

[[home.features]]
title = "Feature Parity"
description = "NeoHotbar utilizes Tool objects and all of its features, just like the default Roblox hotbar."

[navbar]
# hideableSidebar = true
title = "Compatible"
description = "NeoHotbar supports all devices, utilizing all Tool features, improving upon many of them."

[footer]
style = "dark"
copyright = "Copyright © 2023 Avafe. Built with Moonwave and Docusaurus"

# [[footer.docs]]
# title = "Docs"

# [[footer.docs.items]]
# label = "Getting Started"
# href = "https://avafe.me/NeoHotbar/docs/intro"
copyright = "Copyright © 2023 Avafe. Built with Moonwave and Docusaurus"
57 changes: 57 additions & 0 deletions src/Components/ButtonHint.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
local UserInputService = game:GetService("UserInputService")
local NeoHotbar = script.Parent.Parent

local Fusion = require(NeoHotbar.Parent.Fusion)
local FusionUtils = require(NeoHotbar.Parent.FusionUtils)
local States = require(NeoHotbar.States)
local EnsureProp = require(NeoHotbar.ExtPackages.EnsureProp)

local Hydrate = Fusion.Hydrate
local Computed = Fusion.Computed
local Child = FusionUtils.Child
local Spring = Fusion.Spring
local Observer = Fusion.Observer
local Cleanup = Fusion.Cleanup

return function(Props: table)
Props.Keycode = EnsureProp(Props.Keycode, "EnumItem", nil)

local KeycodeImage = Computed(function()
if typeof(Props.Keycode:get()) == "EnumItem" then
return UserInputService:GetImageForKeyCode(Props.Keycode:get())
else
return ""
end
end)
local Shown = Computed(function()
return States.GamepadInUse:get() and (string.len(KeycodeImage:get()) >= 1)
end)
local ObserverDisconnects = {}

local ButtonHint = Hydrate(States.InstanceSet:get()[script.Name]:Clone()) {
[Child "Image"] = {
Image = KeycodeImage,
},

[Cleanup] = function()
for _, Disconnect in ipairs(ObserverDisconnects) do
Disconnect()
end
end
}

if States.DefaultEffectsEnabled:get() then
Hydrate(ButtonHint) {
GroupTransparency = Spring(Computed(function()
return (Shown:get() and 0) or 1
end), 40, 1),
}
end

table.insert(ObserverDisconnects, Observer(Shown):onChange(function()
ButtonHint:SetAttribute("Shown", Shown:get())
end))
ButtonHint:SetAttribute("Shown", Shown:get())

return ButtonHint
end
2 changes: 1 addition & 1 deletion src/Components/ButtonImage.lua
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ local Child = FusionUtils.Child
return function(Props: table)
Props.Image = EnsureProp(Props.Image, "string", "")

return Hydrate(States.InstanceSet:get().ButtonImage:Clone()) {
return Hydrate(States.InstanceSet:get()[script.Name]:Clone()) {
[Child "Image"] = {
Image = Props.Image
}
Expand Down
11 changes: 9 additions & 2 deletions src/Components/ButtonText.lua
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,15 @@ local Hydrate = Fusion.Hydrate
return function(Props: table)
Props.Text = EnsureProp(Props.Text, "string", "Text")

return Hydrate(States.InstanceSet:get().ButtonText:Clone()) {
local ButtonText = Hydrate(States.InstanceSet:get()[script.Name]:Clone()) {
Text = Props.Text,
Font = (States.DefaultEffectsEnabled:get() and Enum.Font.Gotham) or nil,
}

if States.DefaultEffectsEnabled:get() then
Hydrate(ButtonText)({
FontFace = Font.fromName("GothamSsm")
})
end

return ButtonText
end
58 changes: 41 additions & 17 deletions src/Components/ContextActionButton.lua
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,29 @@ local OnEvent = Fusion.OnEvent
local Value = Fusion.Value
local Computed = Fusion.Computed
local Child = FusionUtils.Child
local Observer = Fusion.Observer
local Cleanup = Fusion.Cleanup

return function(Props: table)
Props.Action = EnsureProp(Props.Action, "table", {})

local Hovering = Value(false)
local ObserverDisconnects = {}

return Hydrate(States.InstanceSet:get().ActionButton:Clone())({
BackgroundTransparency = Computed(function()
return (Hovering:get() and 0.975) or 1
end),
local ContextActionButton = Hydrate(States.InstanceSet:get()[script.Name]:Clone()) {
[OnEvent "Activated"] = function()
States.ContextMenu.Active:set(false)

if Props.Action:get() and Props.Action:get().Function then
Props.Action:get():Function()
end
end,
[OnEvent "MouseEnter"] = function()
Hovering:set(true)
end,
[OnEvent "MouseLeave"] = function()
Hovering:set(false)
end,

[Child "Text"] = {
Text = Computed(function()
Expand All @@ -31,18 +44,29 @@ return function(Props: table)
end),
},

[OnEvent("Activated")] = function()
States.ContextMenu.Active:set(false)

if Props.Action:get() and Props.Action:get().Function then
Props.Action:get():Function()
[Cleanup] = function()
for _, Disconnect in ipairs(ObserverDisconnects) do
Disconnect()
end
end,
[OnEvent("MouseEnter")] = function()
Hovering:set(true)
end,
[OnEvent("MouseLeave")] = function()
Hovering:set(false)
end,
})
end
}

if States.DefaultEffectsEnabled:get() then
Hydrate(ContextActionButton) {
BackgroundTransparency = Computed(function()
return (Hovering:get() and 0.925) or 1
end),

[Child "Text"] = {
FontFace = Font.fromName("GothamSsm")
}
}
end

table.insert(ObserverDisconnects, Observer(Hovering):onChange(function()
ContextActionButton:SetAttribute("Hovering", Hovering:get())
end))
ContextActionButton:SetAttribute("Hovering", Hovering:get())

return ContextActionButton
end
5 changes: 2 additions & 3 deletions src/Components/ContextMenu.lua
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ local FusionUtils = require(NeoHotbar.Parent.FusionUtils)
local States = require(NeoHotbar.States)

local Hydrate = Fusion.Hydrate
local Computed = Fusion.Computed
local Child = FusionUtils.Child
local Children = Fusion.Children
local ForValues = Fusion.ForValues
Expand All @@ -14,7 +13,7 @@ local Components = NeoHotbar.Components
local ContextActionButton = require(Components.ContextActionButton)

return function()
return Hydrate(States.InstanceSet:get().ContextMenu:Clone())({
return Hydrate(States.InstanceSet:get()[script.Name]:Clone()) {
Visible = States.ContextMenu.Active,

[Child "Actions"] = {
Expand All @@ -26,5 +25,5 @@ return function()
end, Fusion.cleanup),
},
},
})
}
end
9 changes: 7 additions & 2 deletions src/Components/CustomButton.lua
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,15 @@ local Hydrate = Fusion.Hydrate
local Components = NeoHotbar.Components

local ButtonImage = require(Components.ButtonImage)
local ButtonHint = require(Components.ButtonHint)

return function(Props: table)
Props.LayoutOrder = EnsureProp(Props.LayoutOrder, "number", "0")
Props.LayoutOrder = EnsureProp(Props.LayoutOrder, "number", 0)
Props.Callback = EnsureProp(Props.Callback, "function", function()end)
Props.Icon = EnsureProp(Props.Icon, "string", "")
Props.GamepadKeybind = EnsureProp(Props.GamepadKeybind, "EnumItem", nil)

return Hydrate(States.InstanceSet:get().CustomButton:Clone()) {
return Hydrate(States.InstanceSet:get()[script.Name]:Clone()) {
LayoutOrder = Props.LayoutOrder,

[OnEvent "Activated"] = function()
Expand All @@ -29,6 +31,9 @@ return function(Props: table)
[Children] = {
ButtonImage {
Image = Props.Icon
},
ButtonHint {
Keycode = Props.GamepadKeybind
}
}
}
Expand Down
Loading

0 comments on commit 8a95fb1

Please sign in to comment.