[beta 0.22] Jexplorer | Stylizable explorer widget, made with JECS

a problem i had with this is that when i have this plugin enabled (just in plugin settings) it hangs the entire studio window for a minute or something (excluding qt ui) and when i close it during this hang it reached 11gb memory usage, when i disabled the plugin i had no such problem

interacting with parts past this hang would also make small hangs

1 Like

That’s the issue. The InputBegan event detects mouse enter too. You could try filtering mouse enter events out, but I’m not sure how — but you do get some information about the input through a InputObject instance.

Yea this is really just because of the apiservice which contains the entire roblox api reference :skull: I’ve been considering using require-by-id but that risks getting taken down, gonna try out a workaround

Once ReflectionService releases this shouldn’t really be an issue

The small hangs are really just reuse and assign queues being flushed, I’ll try adding some deferring to them so the impact is spread out

1 Like

Ah i’ll try filtering out UserInputType.MouseMovement

Do you really need it all? Don’t you just need properties?

Yes, I need properties for all instances, I couldn’t find a library that only contained those though so apiservice it was

Even with just the classes it’s still multiple hundreds of thousands of lines of json

Perfect. Here you go:
PropertiesMap.rbxm (1.9 KB)
It’s way more optimized, provide only the properties like you want, is always-up-to-date, and inherits from superclasses.

How to use:

local properties = require(path.to.PropertiesMap)

print(properties.Part) -- Prints all properties of instance `Part`.

I made it btw (because I’m using it for the upcoming V2 for my Tween+ library) :slight_smile:

1 Like

Also it will provide the type of each property. This is the layout:

properties = {
	instanceName = {
		propertyName = propertyType
	}
}
1 Like

Hi, in the newest update I’ve cached some queries and changed the big json api reference into using alexander’s httpservice one instead, this made selection and expansion (for me atleast) faster with no hangs

Though any hangs you’ll further experience is really just the plugin lazy loading certain stuff such as icons and cached instance frames (i’ll probably increase the initial target cache limit for instance frames so you don’t have to expand stuff to get it going)

Though the initial hang unfortunately still exists because of the initial http request for instance properties, this issue will not be resolved until the enabling of ReflectionService

1 Like

Also I’ve filtered out Enum.UserInputType.MouseMovement for instance list close detection + made the search box reset and automatically focus on open

1 Like

You still haven’t changed this to false :frowning:

-- Jexplorer.Manager

local jexplorerWidget = plugin:CreateDockWidgetPluginGui(
	getId("Jexplorer"), DockWidgetPluginGuiInfo.new(
		Enum.InitialDockState.Left,
		false,
		true -- THIS
	)
)

Ive changed it to false :thinking: My widget reappears once i restart the plugin

Maybe i forgot, in which case ill have to do that tomorrow because its bedtime :sweat_smile:

1 Like

Nevermind, it’s all good! Goodnight.

1 Like

Issue:
Scripts with RunContext set to Client are not given the LocalScript icon.


Suggestion:
Add keyboard navigation (via the up and down arrow keys) to the instance insert menu:

  • The highlighted/selected instance should be set to the top instance when opening the menu AND when typing in the search box.

  • When the Enter/Return key is pressed, it should insert the selected instance.

1 Like

@athar_adv I fixed game runtime retrieval for plugins (I think):
PropertiesMap.rbxm (2.1 KB)

1 Like

Hey guys, I know this isn’t really an update but I wanted to make this for those of you who prefer using code to modify the explorer

All essential Jexplorer APIs are now exposed via shared.Jexplorer which means you can make your own custom extension plugins for Jexplorer and do stuff like this!:

Heres some stuff to get you an idea of what’s contained within this new exposed api:


Types file (describes what’s contained within each module)

--!strict

local main = script.Parent

local utilities = main.Utilities
local ui = main.UI

local PluginUI = require(utilities.PluginUI)
local Style = require(utilities.Style)
local Group = require(utilities.Group)
local SimpleSignal = require(utilities.SimpleSignal)
local Jecs = require(main.Jecs)

type Signal<T... = ()> = SimpleSignal.SimpleSignal<T...>
export type WidgetState = {
	World: World,
	Connections: Group.Group,
	Entities: {InstanceEntity},
	Widget: DockWidgetPluginGui,
	CurrentSelection: {InstanceEntity},
	HierarchyVersion: number,

	LastSelectedEntity: InstanceEntity?,
	ContextTarget: InstanceEntity?,

	CurrentlyRenaming: InstanceEntity?,
	CurrentlyInserting: {Instance}?,
	CurrentDrag: {
		Connections: Group.Group,
		Frame: typeof(ui.DragFrame),
		Entities: {InstanceEntity}
	}?,

	JExplorerUI: typeof(ui.JExplorerUi),
}
export type StudioIconResult = {
	Image: string,
	ImageRectOffset: Vector2,
	ImageRectSize: Vector2
}
export type InstanceFrame = {
	Instance: typeof(ui.InstanceFrame),
	Connections: Group.Group,
	CurrentEntity: InstanceEntity?,
	
	Assign: (InstanceFrame, entity: InstanceEntity?, parent: InstanceEntity?) -> (),
	ReassignNametags: (InstanceFrame, newName: string, className: string) -> (),
	ToggleSelection: (InstanceFrame, selected: boolean) -> (),
	Reuse: (InstanceFrame) -> ()
}

export type World = Jecs.World
type SelectedComponent = Jecs.Id
type ExpandedComponent = Jecs.Id
type VisibleComponent = Jecs.Id
type IsQueriedComponent = Jecs.Id
type FrameComponent = Jecs.Id<InstanceFrame>
type ConnectionsComponent = Jecs.Id<Group.Group>
type InstanceComponent = Jecs.Id<Instance>

export type InstanceEntity = Jecs.Id

type Components = {
	Selected: SelectedComponent,
	Expanded: ExpandedComponent,
	Instance: InstanceComponent,
	Frame: FrameComponent,
	Connections: ConnectionsComponent,
	Invisible: VisibleComponent,
	IsQueried: IsQueriedComponent
}

export type Manager = {
	WidgetState: WidgetState,
	Components: Components,
	
	ContextMenus: {
		Service: PluginMenu,
		Instance: PluginMenu
	},
	ItemLists: {
		InsertInstance: PluginUI.ItemList
	},
	Style: Style.Style,
	InstanceToEntity: {[Instance]: InstanceEntity},
	FrameToInstanceFrame: {[Instance]: InstanceFrame},
	
	SelectionChanged: Signal<{InstanceEntity}>,
	
	connectInputBegan: (fn: (input: InputObject) -> ()) -> (),
	connectInputEnded: (fn: (input: InputObject) -> ()) -> (),
	isKeyDown: (key: Enum.KeyCode) -> (boolean),
	isInputActive: (input: Enum.UserInputType) -> (boolean),
	getVisibleEntities: (world: World, parent: InstanceEntity?) -> {InstanceEntity},
	getInstanceFrame: () -> InstanceFrame,
	createInstanceEntity: (instance: Instance, parent: InstanceEntity?) -> InstanceEntity?,
	getSetting: (name: string) -> any,
	setInstanceFramePoolTarget: (n: number) -> (),
	fillInstanceFramePoolToLimit: () -> (),
	addEntitiesToSelection: (world: World, entities: {InstanceEntity}) -> (),
	updateVirtualScroller: () -> (),
	
	init: (onClose: () -> (), pluginVersion: string, connections: Group.Group) -> ()
}

export type StyleEditor = {
	StyleEditorWidget: DockWidgetPluginGui,
	
	init: (Manager: Manager, sheet: Style.Style) -> (),
}

export type SettingEditor = {
	SettingEditorWidget: DockWidgetPluginGui,
	
	getSetting: (Manager: Manager, name: string) -> any,
	createSetting: (list: PluginUI.ItemList, settingName: string, displayName: string, valueType: string, defaultValue: any, onChange: ((newValue: any) -> ())?) -> (),
	
	init: (Manager: Manager) -> (),
}

return nil

Hopefully I’ll be able to make a more indepth guide but I have some thingsi gotta do

3 Likes

Yes later I’m gonna add property modifier icons which should be what you’re looking for
Also yea gonna add up/down arrow and enter to insert to insert instance menu too

1 Like

Yea I’d say focus on the development of the plugin.

1 Like

Nevermind. It was a bit more complicated to fix. This should work:

PropertiesMap.rbxm (2.2 KB)

You’ll have to now retrieve it like this:

local properties = require(path.to.PropertiesMap)(plugin)

Also:


(Why use the deprecated wait function rather than task.wait?)

1 Like

Wanted it to throttle incase u have a big hang :V