It was just how Ode was designed, and changing it would take too much time at the moment.
You inspired me to make my own!
Version 1.1.0
Thank you @pinehappi for contributing.
This version implements the :Destroy()
method and .AutoWrapEnabled
field. The Creator Store version has not yet been updated, but the rbxm file has been uploaded to GitHub. Below are the release notes generated by GitHub.
Whatâs Changed
- Fix y-drift of rich text overlays and line numbers by @pinehappi in #1
- Implement destroy method by @SpaceDice9 in #3
- Improve lexer accuracy by @SpaceDice9 in #4
- Fix performance drop when scrolling with large source data by @SpaceDice9 in #5
- Fix CodeField not updating correctly when resizing container frame by @SpaceDice9 in #6
- Implement autowrapping for some characters by @SpaceDice9 in #7
New Contributors
- @pinehappi made their first contribution in #1
Full Changelog: Commits ¡ SpaceDice9/OdeScriptEditor ¡ GitHub
Iâm having an issue with displaying the text color
Can you show a screenshot and error logs if any? Also make sure to give me a place file where I can recreate the issue.
There is no error actually. I just took the model as it was from the model on your github and added it to a baseplate.
The one listed as a release is a little outdated compared to the git repo itself. Try this one and see if the problem persists.
OdeScriptEditor.rbxm (33.0 KB)
This is so cool, it makes it 10 times easier than writing quick scripts from the dev console.
Tysm, this saved me so much time, thereâs 1 issues with it is that itâs not really optimized since it has to modify the entire rich text everytime
Thatâs strange. Works perfectly for me. Are you initializing Ode correctly? This is how I do it.
local Ode = require(game.ReplicatedStorage.OdeScriptEditor)
local frame: Frame = script.Parent.Frame
Ode.Embed(frame)
Also, if you still have the place file (the .rbxl
one) please send it to me so I can help you diagnose the issue
Alright, I just tried initializing it like you stated above but nothing changes. Here is the .rbxl file
Editor.rbxl (89.0 KB)
can be used in game? i want to make a runtime dev only executor (not for hacks just for debugging) in live serve4s
I see the problem now. The initializer script needs to be a local script to run properly. That fixes the issue.
Alright, thank you for the help.
Sure! Keep in mind however that this is just an editor and has no execution functionality. That is something you would have to implement yourself. Also, Iâve seen that older versions might not work properly under a fully published game so make sure to grab the latest one using Rojo if possible (this version also has a slightly different api, :LoadScriptAsync
and :LoadStringAsync
are replaced with :SetScriptAsync
and :SetStringAsync
. If you canât, I can provide the file here:
OdeScriptEditor.rbxm (24.4 KB)
I was having problems with deleting text when the text went over the screen. To fix it I made this adjustment to the GetTextBoxScrolling module script
local TextService = game:GetService(âTextServiceâ)
â Only works when font is monospaced and x size is exactly C * width of character + 1 (6 * 7 + 1 = 43)
function getMultiLinePositions(text)
local multilines = string.split(text, â\nâ)
local multilinePositions = {}
local cursor = 1
local maxLineLength = 0
local maxLineIndex = -1
for i, line in multilines do
local lineLength = string.len(line)
table.insert(multilinePositions, {cursor, cursor + lineLength})
if lineLength > maxLineLength then
maxLineLength = lineLength
maxLineIndex = i
end
cursor += lineLength + 1
end
return multilines, multilinePositions, maxLineLength, maxLineIndex
end
function getLinePosition(multilinePositions, position)
for i, multilinePosition in multilinePositions do
if (position >= multilinePosition[1] and position <= multilinePosition[2]) then
return i, position - multilinePosition[1] + 1
end
end
return -1, -1
end
function getLengthOfLine(text, textLabel: TextBox)
local absoluteSize = TextService:GetTextSize(
text,
textLabel.TextSize,
textLabel.Font,
Vector2.new(math.huge, math.huge)
)
return absoluteSize.X
end
function getShiftAmount(lower, upper, maxlength, windowWidth, x)
âprint(string.format(âLineLength: %d MaxLength: %d, Width: %d, Lower: %d, Upper: %dâ, x, maxlength or -1, windowWidth, lower, upper))
if maxlength and maxlength < upper then
return maxlength - upper
elseif x < lower then
return x - lower
elseif x > upper then
return x - upper
else
return 0
end
end
local GetTextBoxScrolling = {}
function GetTextBoxScrolling.UpdateShift(textLabel: TextBox, cursorPosition, shift)
if cursorPosition == -1 then
return 0
end
â print(âUpdate Shiftâ)
local labelWindow = textLabel.AbsoluteSize.X - 1
local multilines, multilinePositions, maxLinePosition, maxLineIndex = getMultiLinePositions(textLabel.Text)
local linePosition, positionLength = getLinePosition(multilinePositions, cursorPosition)
local line = multilines[linePosition]
local stringUntilCursor = string.sub(line, 0, positionLength - 1)
local lineLength = getLengthOfLine(stringUntilCursor, textLabel)
local maxLineLength = (maxLineIndex > 0) and getLengthOfLine(multilines[maxLineIndex], textLabel)
local relativeShift = getShiftAmount(shift, shift + labelWindow, maxLineLength, labelWindow, lineLength)
shift = math.max(0, shift + relativeShift)
--print(shift, relativeShift)
return shift
end
return GetTextBoxScrolling
Can you submit your changes on GitHub? The code snippet you sent here is badly formatted. When writing code snippets on the DevForum please use ``` to denote code.
I donât know how to submit it on GitHub, so Iâll submit it here with properly formatted code.
The issue was when the line youâre editing goes beyond the horizontal window space, deleting from that line would desync the underlying text from the textbox with the rich overlay text.
What I changed:
- I calculate the max horizontal length of the entire text and used it in getShiftAmount() to properly sync it
Ignore the maxShift return field in UpdateShift(), it was part with a horizontal scroll bar I added. The horizontal scroll bar works but it desyncs the text again (because the TextBox only scrolls horizontally when focused). I propose removing the CodeField textbox entirely and making your own input events, fake cursor, and text selection functionality. The base CodeField functionality doesnt work well with new features like horizontal scroll.
GetTextBoxScrolling.lua
local TextService = game:GetService("TextService")
-- Only works when font is monospaced and x size is exactly C * width of character + 1 (6 * 7 + 1 = 43)
function getMultiLinePositions(text)
local multilines = string.split(text, "\n")
local multilinePositions = {}
local cursor = 1
local maxLineLength = 0
local maxLineIndex = -1
for i, line in multilines do
local lineLength = string.len(line)
table.insert(multilinePositions, {cursor, cursor + lineLength})
if lineLength > maxLineLength then
maxLineLength = lineLength
maxLineIndex = i
end
cursor += lineLength + 1
end
return multilines, multilinePositions, maxLineLength, maxLineIndex
end
function getLinePosition(multilinePositions, position)
for i, multilinePosition in multilinePositions do
if (position >= multilinePosition[1] and position <= multilinePosition[2]) then
return i, position - multilinePosition[1] + 1
end
end
return -1, -1
end
function getLengthOfLine(text, textLabel: TextBox)
local absoluteSize = TextService:GetTextSize(
text,
textLabel.TextSize,
textLabel.Font,
Vector2.new(math.huge, math.huge)
)
return absoluteSize.X
end
function getShiftAmount(lower, upper, maxlength, windowWidth, x)
--print(string.format("LineLength: %d MaxLength: %d, Width: %d, Lower: %d, Upper: %d", x, maxlength or -1, windowWidth, lower, upper))
if maxlength and maxlength < upper then
return maxlength - upper
elseif x < lower then
return x - lower
elseif x > upper then
return x - upper
else
return 0
end
end
local GetTextBoxScrolling = {}
function GetTextBoxScrolling.UpdateShift(textLabel: TextBox, cursorPosition, shift)
if cursorPosition == -1 then
return shift
end
-- print("Update Shift")
local labelWindow = textLabel.AbsoluteSize.X - 1
local multilines, multilinePositions, maxLinePosition, maxLineIndex = getMultiLinePositions(textLabel.Text)
local linePosition, positionLength = getLinePosition(multilinePositions, cursorPosition)
local line = multilines[linePosition]
local stringUntilCursor = string.sub(line, 0, positionLength - 1)
local lineLength = getLengthOfLine(stringUntilCursor, textLabel)
local maxLineLength = (maxLineIndex > 0) and getLengthOfLine(multilines[maxLineIndex], textLabel)
local relativeShift = getShiftAmount(shift, shift + labelWindow, maxLineLength, labelWindow, lineLength)
local maxShift = if maxLineLength then math.max(0, maxLineLength - labelWindow) else 0
shift = math.max(0, shift + relativeShift)
--print(shift, relativeShift)
return shift, maxShift
end
return GetTextBoxScrolling