import { ArcHandles } from "Adornment/ArcHandles"; import { doorAdornment } from "Adornment/Exit"; import { Handles } from "Adornment/Handles"; import CollapsibleTitledSection from "Lualibs/CollapsibleTitledSection"; import CustomTextButton from "Lualibs/CustomTextButton"; import LabeledTextInput from "Lualibs/LabeledTextInput"; import VerticallyScalingListFrame from "Lualibs/VerticallyScalingListFrame"; import VerticalScrollingFrame from "Lualibs/VerticalScrollingFrame"; import { syncGuiColors } from "Utils/Gui"; import { RoomConfig } from "Utils/Room"; export class RoomWidget { plugin: Plugin; model: Folder; info: DockWidgetPluginGuiInfo; widget: DockWidgetPluginGui; noRoomLabel: TextLabel; scrollFrame = new VerticalScrollingFrame("RoomScroll"); listFrame = new VerticallyScalingListFrame("RoomWidget"); roomCollapse = new CollapsibleTitledSection( "roomCollapse", // name suffix of the gui object "Room", // the text displayed beside the collapsible arrow true, // have the content frame auto-update its size? true, // minimizable? false, // minimized by default? ); exitsCollapse = new CollapsibleTitledSection( "ExitCollapse", // name suffix of the gui object "Exit", // title text of the collapsible arrow true, // have the content frame auto-update its size? true, // minimizable? false, // minimized by default? ); roomIdValue = new Instance("IntValue"); roomIdInput = new LabeledTextInput( "RoomId", // name suffix of gui object "Room Id", // title text of the multi choice "0", // default value ); roomTypeValue = new Instance("StringValue"); roomTypeInput = new LabeledTextInput( "RoomType", // name suffix of gui object "Room Type", // title text of the multi choice "", // default value ); constructor(plugin: Plugin, model: Folder) { this.plugin = plugin; this.model = model; this.info = new DockWidgetPluginGuiInfo(Enum.InitialDockState.Left, false, false, 200, 300, 150, 150); this.widget = plugin.CreateDockWidgetPluginGui("RoomWidget", this.info); (this.widget as unknown as { Title: string }).Title = "Room Info"; this.noRoomLabel = new Instance("TextLabel"); this.noRoomLabel.Text = "Select a room to use this widget."; this.noRoomLabel.Size = new UDim2(1, 0, 1, 0); syncGuiColors(this.noRoomLabel); this.roomIdInput.SetValueChangedFunction((value) => { this.roomIdValue.Value = tonumber(value) ?? 0; }); this.roomTypeInput.SetMaxGraphemes(255); this.roomTypeInput.SetValueChangedFunction((value) => { this.roomTypeValue.Value = value; }); // Setup Widget this.roomIdInput.GetFrame().Parent = this.roomCollapse.GetContentsFrame(); const idTextBox = this.roomIdInput.GetFrame().FindFirstChildWhichIsA("TextBox", true)!; idTextBox.ClearTextOnFocus = false; this.roomTypeInput.GetFrame().Parent = this.roomCollapse.GetContentsFrame(); const typeTextBox = this.roomTypeInput.GetFrame().FindFirstChildWhichIsA("TextBox", true)!; typeTextBox.ClearTextOnFocus = false; this.listFrame.AddChild(this.roomCollapse.GetSectionFrame()); this.listFrame.AddChild(this.exitsCollapse.GetSectionFrame()); this.listFrame.AddBottomPadding(); this.listFrame.GetFrame().Parent = this.scrollFrame.GetContentsFrame(); this.scrollFrame.GetSectionFrame().Parent = this.widget; this.noRoomLabel.Parent = this.widget; } UpdateValue(config: RoomConfig) { this.roomIdValue = config.RoomId; this.roomIdInput.SetValue(tostring(config.RoomId.Value)); this.roomTypeValue = config.RoomType; this.roomTypeInput.SetValue(config.RoomType.Value); const exits = config .GetChildren() .filter( (value) => !string.match(value.Name, "^Exit_[0-9]+$").isEmpty() && value.IsA("CFrameValue"), ) as CFrameValue[]; this.ReloadExits(exits, config); } SetActive(active: boolean) { this.noRoomLabel.Visible = !active; } ReloadExits(exits: CFrameValue[], config: RoomConfig) { this.exitsCollapse.GetContentsFrame().ClearAllChildren(); const exitListFrame = new VerticallyScalingListFrame("RoomWidget"); for (const exit of exits) { const posbutton = new CustomTextButton( "edit_button", // name of the gui object `Edit ${exit.Name} position`, // the text displayed on the button ); const posbuttonobject = posbutton.GetButton() as ImageButton; posbuttonobject.Activated.Connect(() => { this.LoadExitMoveHandles(exit); }); posbuttonobject.Size = new UDim2(0, 150, 0, 20); const rotbutton = new CustomTextButton( "edit_button", // name of the gui object `Edit ${exit.Name} rotation`, // the text displayed on the button ); const rotbuttonobject = rotbutton.GetButton() as ImageButton; rotbuttonobject.Activated.Connect(() => { this.LoadExitRotationHandles(exit); }); rotbuttonobject.Size = new UDim2(0, 150, 0, 20); exitListFrame.AddChild(posbuttonobject); exitListFrame.AddChild(rotbuttonobject); } const rotbutton = new CustomTextButton( "create_button", // name of the gui object `Create a Exit`, // the text displayed on the button ); const createbutobject = rotbutton.GetButton() as ImageButton; createbutobject.Activated.Connect(() => { const exit = new Instance("CFrameValue"); exit.Parent = config; exit.Value = new CFrame(config.Origin.Value); exit.Name = `Exit_${exits.size()}`; exits.push(exit); this.ReloadExits(exits, config); }); createbutobject.Size = new UDim2(0, 150, 0, 20); exitListFrame.AddChild(createbutobject); exitListFrame.AddBottomPadding(); exitListFrame.GetFrame().Parent = this.exitsCollapse.GetContentsFrame(); } LoadExitMoveHandles(exit: CFrameValue) { this.clearExitHandles(); const folder = new Instance("Folder"); folder.Parent = this.model; folder.Name = "_exit_handle"; const exithandle = new Handles(folder, exit.Value.Position); exithandle.valueChanged.Connect((value) => { const oldvalue = exit.Value; exit.Value = new CFrame(value).mul(oldvalue.sub(oldvalue.Position)); }); doorAdornment(folder, exithandle.anchor); } LoadExitRotationHandles(exit: CFrameValue) { this.clearExitHandles(); const folder = new Instance("Folder"); folder.Parent = this.model; folder.Name = "_exit_handle"; const exithandle = new ArcHandles(folder, exit.Value); exithandle.valueChanged.Connect((value) => { const oldvalue = exit.Value; exit.Value = new CFrame(oldvalue.Position).mul(value.Rotation); }); doorAdornment(folder, exithandle.anchor); } clearExitHandles() { const childs = this.model.GetChildren(); childs .filter((value) => value.Name === "_exit_handle") .forEach((value) => { value.Destroy(); }); } }