Jump to content
Zita

Need a script for contentbrowerhack

Recommended Posts

I have an ugly suspicion... since the code does not actually draw anything on the screen it may be ignored by Reflex and thus

ui_show_widget contentHack

is removed from the game.cfg again and again.

Share this post


Link to post
Share on other sites

I finally think I have it:

    -- Early out if HUD should not be shown.
1   if not shouldShowHUD() then return end; -- messes up things in edit mode

2    local player = getPlayer();
3    if player.state ~= PLAYER_STATE_EDITOR then return end -- only do this in editor mode

this is a really convoluted problem.

  • Now for the .lua to load without an error line 1 is required, is it missing, the widget shows an error regarding line 3. since player=nil in the main menu where no player is accessible.
  • And when the widget shows an error Reflex automatically turns it off. So once you loaded a map and are in edit mode the script is no longer shown. And you need to manually ui_show_widget ContentHack.
  • So line 1 is vital. Ironically this line prohibits the widget from running in editor mode.
  • So one probably could drop lines 1 to 3... but then the widget would also be running in game mode, ALL the time.

So we need a different shouldShowHUD() function that does not block widgets running in editor mode.

 

This seems to work:

-- Reflexbaseinternaluiwidgets_customContentHack.lua
--                                        ---------------
require "base/internal/ui/reflexcore"

ContentHack =
{
	canHide = false,
	canPosition = false
};
registerWidget("ContentHack");

local contentList =
{
	--Materials with grids
	"structural/dev/dev_aqua",
	"structural/dev/dev_aquaddark",
	"structural/dev/dev_black",
	"structural/dev/dev_blue",
	"structural/dev/dev_bluedark",
	"structural/dev/dev_bluelight",
	"structural/dev/dev_green",
	"structural/dev/dev_greendark",
	"structural/dev/dev_greenlight",
	"structural/dev/dev_grey128",
	"structural/dev/dev_grey192",
	"structural/dev/dev_grey64",
	"structural/dev/dev_lime",
	"structural/dev/dev_magenta",
	"structural/dev/dev_magentadark",
	"structural/dev/dev_orange",
	"structural/dev/dev_orangedark",
	"structural/dev/dev_pink",
	"structural/dev/dev_pinkdark",
	"structural/dev/dev_purple",
	"structural/dev/dev_purpledark",
	"structural/dev/dev_red",
	"structural/dev/dev_reddark",
	"structural/dev/dev_white",
	"structural/dev/dev_yellow",
	"structural/dev/dev_yellowdark",

	--Materials without grids
	"structural/dev/dev_nogrid_aqua",
	"structural/dev/dev_nogrid_aquadark",
	"structural/dev/dev_nogrid_black",
	"structural/dev/dev_nogrid_bluedark",
	"structural/dev/dev_nogrid_bluelight",
	"structural/dev/dev_nogrid_green",
	"structural/dev/dev_nogrid_greendark",
	"structural/dev/dev_nogrid_greenlight",
	"structural/dev/dev_nogrid_grey128",
	"structural/dev/dev_nogrid_grey192",
	"structural/dev/dev_nogrid_grey64",
	"structural/dev/dev_nogrid_lime",
	"structural/dev/dev_nogrid_limedark",
	"structural/dev/dev_nogrid_magenta",
	"structural/dev/dev_nogrid_magentadark",
	"structural/dev/dev_nogrid_orange",
	"structural/dev/dev_nogrid_orangedark",
	"structural/dev/dev_nogrid_pink",
	"structural/dev/dev_nogrid_pinkdark",
	"structural/dev/dev_nogrid_purple",
	"structural/dev/dev_nogrid_purpledark",
	"structural/dev/dev_nogrid_red",
	"structural/dev/dev_nogrid_reddark",
	"structural/dev/dev_nogrid_white",
	"structural/dev/dev_nogrid_yellow",
	"structural/dev/dev_nogrid_yellowdark",

	--Materials Trims
	"structural/dev/dev_bluelight_trim",
	"structural/dev/dev_blue_trim",
	"structural/dev/dev_greenlight_trim",
	"structural/dev/dev_green_trim",
	"structural/dev/dev_grey192_trim",
	"structural/dev/dev_orange_trim",
	"structural/dev/dev_purple_trim",
	"structural/dev/dev_red_trim",
	"structural/dev/dev_yellow_trim"
}

local crosshair = 0		-- crosshair turned off in edit mode
local pos = 0    -- 0 is the correct initial value, and
                 -- pos value is remembered between widget calls

function ContentHack:draw()

	-- Early out if HUD should not be shown.
--	if not shouldShowHUD() then return end; -- messes up things in edit mode

--	local player = getPlayer();
--	if player.state ~= PLAYER_STATE_EDITOR then return end -- only do this in editor mode

	local currentCrosshair = consoleGetVariable("cl_crosshair")
	if currentCrosshair < 888 or currentCrosshair > 889 then return end; -- quick out

	local n = table.getn(contentList);

	if currentCrosshair == 888 then
		setNextMaterial = true
		pos = pos + 1
		if pos > n then pos = 1 end -- looping array
	elseif currentCrosshair == 889 then
		setPrevMaterial = true
		pos = pos - 1
		if pos < 1 then pos = n end
	else
		return
	end

	consolePerformCommand("me_activematerial " .. contentList[pos])

	-- reset crosshair (i.e. turn it off again)
	consolePerformCommand("cl_crosshair " .. crosshair)

end

only downside... it runs during the game mode as well, and for some stupid reason "ui_show_widget ContentHack" is still getting deleted from the game.cfg file when you "quit" Reflex from the console :(

Share this post


Link to post
Share on other sites

This should make you happier, tossed this all into a scrollable menu, SOME of the content doesn't set to me_activematerial, Because it doesn't belong there anyway. if someone want's to break down that array into correct categories i.e

i'll look into breaking it down into tab's or something and atleast get it setting stuff to the correct CVars.

 

http://pastebin.com/W3jHcsZw

 

it should default bind f9 to show/hide it, and is on the main menu on far right.

use the ingame Cvars to position/scale where ever you want it.

 

ui_set_widget_offset x y

ui_set_widget_scale #

ui_set_widget_anchor x y

content = {
 materials = {  --me_activematerial stuff
      "material/locations"
 },
 createTypes = {
     "creattype/stuff"
 },
 effects = {
     "effects/MOAR"
 }
}

Share this post


Link to post
Share on other sites

AEon lookup the functions in reflexcore.lua

 

oh and for the materials --> https://gist.github.com/Bonuspunkt/64388affb92d5d4b03be

 

if anyone wants to generate it themself here is the c# code for it

using System;
using System.IO;
using System.Linq;

namespace extract
{
    class Program
    {
        static void Main(string[] args)
        {
            string[] extension = { ".effect", ".mesh", ".material" };
            var fileGroup = Directory.GetFiles(".", "*.*", SearchOption.AllDirectories)
                .Select(file => new FileInfo(file))
                .Where(file => extension.Any(ext => file.Extension == ext))
                .GroupBy(file => file.Extension);

            Console.WriteLine("{");
            foreach (var group in fileGroup)
            {
                Console.WriteLine(""" + group.Key + "" = {");
                foreach (var file in group)
                {
                    Console.WriteLine(""" +file.FullName + "",");
                }
                Console.WriteLine("},");
            }
            Console.WriteLine("}");
        }
    }
}

 

Share this post


Link to post
Share on other sites

aliasedfrog,

neat... will give it a try tomorrow. And yes, I also noted that some of the lines are not materials at all, thus will fail with "me_activematerial"... my last copy/paste of the code should have taken that into account mostly.

 

Bonuspunkt,

yeah... had planned to do that tomorrow... for today I have really had it with convoluted debugging of something that should and actually did just work. sigh.

Share this post


Link to post
Share on other sites

aliasedfrog,

looking through your code menu.

 

The menu list is offset by 1... checking what the reason for that is. I.e. the first entry in contentList is ignored, the second one is shown as first entry in the menu, but clicking on this first menu entry actually sets the 1. array entry... strange. Last entry in menu is empty.

 

Strange since this is in uiScrollSelection() a reflexcore.lua function.

Share this post


Link to post
Share on other sites

aliasedfrog,

looking through your code menu.

 

The menu list is offset by 1... checking what the reason for that is. I.e. the first entry in contentList is ignored, the second one is shown as first entry in the menu, but clicking on this first menu entry actually sets the 1. array entry... strange. Last entry in menu is empty.

 

Strange since this is in uiScrollSelection() a reflexcore.lua function.

 

I could have offset the text the wrong direction, I was trying to reference the server browser for that but I was rushing through some of it, if you could look into

 

Line 191 on pasteBin

selection = uiScrollSelection(items, selection, x, y + 50, w, h - 50, ContentHack.scrollBarData, itemHeight, itemDrawFunction)

it's likely the ( y + 50) try changing to y-50 and see if things line up correctly. or atleast brings the 1st entry into view. if that works let me know and I will fix the pasteBin. won't have to test/fix till much later today if you want to check that. otherwise I will find it when I get off work =)

Share this post


Link to post
Share on other sites

Just tried the y-50 and was dubious about this since that should only be a visual offset issue, but we actually are seeing the wrong combo of listed entry on-screen and what it actually selects. So that did not work. I checked the code a bit more and contentList ends up in items it uses a standard

for k, item in pairs(items) do -- in function uiScrollSelection() under reflexcore.lua

so at least there I am not seeing any way the first entry in the contentList array could be skipped. I had thought that the code would be using for i,n ... and that there is some indexing offset somewhere. You could be right that it is some weird gfx offset.

 

aliasedfrog, BTW, in case that may come up, I renamed your widget to ContentHackMenu, to avoid conflicts with my text version ContentHack.

 

Boy am I glad you guys are so much more experienced with LUA... some of the menu code looks as strange as C++ object orientated code... need to do more reading on LUA programming it seems.

Share this post


Link to post
Share on other sites

I looked into the orginal shouldShowHUD() and indeed it explicitly exits when in editor mode, so I duplicated the function under another name, commenting out that one line about the editor and used that function instead: shouldShowHUDAE(). Here the code that now works without any problems:

-- Reflexbaseinternaluiwidgets_customContentHack.lua
--                                        ---------------
require "base/internal/ui/reflexcore"

ContentHack =
{
    canHide = true,      -- true or false does not seem to make any difference
    canPosition = false
};
registerWidget("ContentHack");

local contentList =
{
    --Materials with grids
    "structural/dev/dev_aqua",
    "structural/dev/dev_aquaddark",
    "structural/dev/dev_black",
    "structural/dev/dev_blue",
    "structural/dev/dev_bluedark",
    "structural/dev/dev_bluelight",
    "structural/dev/dev_green",
    "structural/dev/dev_greendark",
    "structural/dev/dev_greenlight",
    "structural/dev/dev_grey128",
    "structural/dev/dev_grey192",
    "structural/dev/dev_grey64",
    "structural/dev/dev_lime",
    "structural/dev/dev_magenta",
    "structural/dev/dev_magentadark",
    "structural/dev/dev_orange",
    "structural/dev/dev_orangedark",
    "structural/dev/dev_pink",
    "structural/dev/dev_pinkdark",
    "structural/dev/dev_purple",
    "structural/dev/dev_purpledark",
    "structural/dev/dev_red",
    "structural/dev/dev_reddark",
    "structural/dev/dev_white",
    "structural/dev/dev_yellow",
    "structural/dev/dev_yellowdark",
    --MORE Materials exist ...
}

local crosshair = 0        -- crosshair turned off in edit mode
local pos = 0    -- 0 is the correct initial value, and
                 -- pos value is remembered between widget calls

-- Special version that does NOT block the editor
function shouldShowHUDAE()
    local player = getPlayer();

    if player == nil
--     or player.state == PLAYER_STATE_EDITOR
       or player.state == PLAYER_STATE_SPECTATOR
       or player.health <= 0
       or world.gameState == GAME_STATE_GAMEOVER
       or consoleGetVariable("cl_show_hud") == 0
       or isInMenu()
       or not player.connected
       then return false end;

    return true;
end

function ContentHack:draw()

    -- Early out if HUD should not be shown.
    if not shouldShowHUDAE() then return end; -- blocks except editor

    local player = getPlayer();
    if player.state ~= PLAYER_STATE_EDITOR then return end -- only do this in editor mode

    local n = table.getn(contentList);

    if currentCrosshair == 888 then
        setNextMaterial = true
        pos = pos + 1
        if pos > n then pos = 1 end -- looping array
    elseif currentCrosshair == 889 then
        setPrevMaterial = true
        pos = pos - 1
        if pos < 1 then pos = n end
    else
        return
    end

    consolePerformCommand("me_activematerial " .. contentList[pos])

    -- reset crosshair (i.e. turn it off again)
    consolePerformCommand("cl_crosshair " .. crosshair)

end

Alas the code works only when you add the line

ui_show_widget ContentHack

to the game.cfg. The widget then works, but as soon as you exit the game via quit on the console, or via game menu disconnect and quit the line is deleted by Reflex. And

    canHide = true,      -- true or false does not seem to make any difference

true or false does not make any difference either.

 

As a hack one could probably add

bind me f10 ui_show_widget ContentHack

to the game.cfg. And every time you launch Reflex and enter editor mode for the first time hit F10 once.

 

 

What the heck could be causing Reflex to not use ui_hide_widget ContentHack but actually keep on deleting the ui_show_widget ContentHack entry from the game.cfg. I just don't get it.

 

Well at least the code per se finally works... sigh.

Share this post


Link to post
Share on other sites

aliasedfrog,

looking through your code menu.

 

The menu list is offset by 1... checking what the reason for that is. I.e. the first entry in contentList is ignored, the second one is shown as first entry in the menu, but clicking on this first menu entry actually sets the 1. array entry... strange. Last entry in menu is empty.

 

Strange since this is in uiScrollSelection() a reflexcore.lua function.

 

This is now fixed on the pasteBin source was like i figured the Y alignment of the drawText was off for some reason, not  sure why. but should be fine now, if someone notices it's out of wack let me know, but i'll prolly start working on doing a tabbed version with 'material/effect' so you don't have a bunch of random stuff that doesn't work in that list.

 

 

(EDIT) updated with tabs and the material's list bonuspunkt pasted i don't have time to go thru and sort what works and doesn't. so don't be suprised when alot of them don't set properly

 

also didn't have time to figure out what was going on with effect/meshes. if you know the proper way to set them in console drop me a msg and i'll fix it so it can set them from the UI

http://pastebin.com/W3jHcsZw

Share this post


Link to post
Share on other sites

AEon ok dont seem to work.

I have copied the code in to ContentHack.lua

 

In the game.cfg I have

bind me mousewheelup cl_crosshair 888
bind me mousewheeldown cl_crosshair 889

bind me f9 ui_show_widget ContentHack

I start map with empty file press 0 to enter editor mode press F9 use scroll wheel but nothing is happening.

 

I dont know if this has any thing to do with it, but there is a line in my game.cfg file now called cl_crosshair 889

now i did have it set to cl_crosshair 4

I have tried to // (comment it out) but when  i exit the game the cl_crosshair 889 is back same happens if i del it from the game.cfg file.

 

Thanks for all the hard work m8, sorry i cant seem to get it to work

 

Share this post


Link to post
Share on other sites

aliasedfrog,

Effects and meshes where a manual copy/paste into the properties window. I don't think there was a "me_activeeffect"-like console command. So one would need to be able to actually add a new entity to the map with that effect or mesh. No idea if any of that is exposed... probably not.

 

Will do a diff on your new code and check how you fixed the offset issue. Thanks.

 

Update: OK tracked down the issue...

    selection = uiScrollSelection(items, selection, x, y + UI_WINDOW_HEADER_HEIGHT, w, h - UI_WINDOW_HEADER_HEIGHT, ContentHackMenu.scrollBarData, itemHeight, itemDrawFunction)

was replaced with

selection = uiScrollSelection(items, selection, x, y + UI_WINDOW_HEADER_HEIGHT, w, h - UI_WINDOW_HEADER_HEIGHT, ContentHackMenu.scrollBarData, itemHeight, uiScrollItem)

 

Now your old code works fine. It makes one's head swim ;). Next checking your new code.

 

Update 2: Put the

MATERIAL_LIST = {

into

require "base/internal/ui/widgets_custom/ContentHackMenu_MaterialList"

to remove the data from the, and named ContentHack -> ContentHackMenu... works really well, and also looks very nice. The tabbing is great.

Share this post


Link to post
Share on other sites

Zita,

as a quick test, try to add the line "ui_show_widget ContentHack" to the game.cfg, and run Reflex. It should work at least the first time. You are using my latest version with the shouldShowHUDAE() function, right?

 

When the widget does not load the mousewheel bindings will mess up the crosshair numbers and these will stick, to resetting to "cl_crosshair 0" in the console helps the widget when it finally runs. But this should no longer be required... hmm...

 

I have not tried the "hack" using a binding... checking that now.

 

Update: Well for some reason suddenly "ui_show_widget ContentHack" stays remembered in the game.cfg. Just when I wanted to test the binding... sigh... no idea what's up. (see above comment updates).

 

Update 2: I presently am running Reflex from a desktop icon

D:GamesSteamsteamappscommonReflexreflex.exe and Steam is NOT running in the background. Should that make any difference.

 

Update 3: The .lua is somewhere under base right? Mine is in a separate custom folder under ui:

D:GamesSteamsteamappscommonReflexbaseinternaluiwidgets_customcontentHack.lua

Update 4: What I do to test the .lua file:

  1. Launch Reflex
  2. Under Start Server Menu, select cmp1 and press go button to load the map.
  3. Then hit the editor key (0 by default) to switch to editor mode. I use mouse3 and this binding and set the crosshair to 0... maybe that helps for some reason:
bind game mouse3 toggleeditor; cl_show_hud 1; cl_crosshair 0

      4. Then in edit mode I can scroll the material entries using:

bind me h cl_crosshair 889
bind me j cl_crosshair 888

 My bindings are a bit different but yours should also work. No idea why any of my bindings should make a difference though.

 

Update 5: Ensure that no older version of ContentHack widget exists anywhere in your Reflexbase and below path...

 

Update 6: Running Reflex with a loaded map and in Editor mode, type ui_show_widget ContentHack on the console, this should load the widget. When with an external text editor e.g. notepad or ultraedit, slightly chnage the ContentHack.lua file e.g. add a comment somewhere and save the file. Then check in Reflex's console, to ensure Reflex is not seeing some error in the .lua code.

Share this post


Link to post
Share on other sites

aliasedfrog,

I wonder if the LUA code lets widgets load and show textures... .dds files in this case. A preview image to the selected material etc. in the ContentHack would be really great. BTW, amazing how fast a programmer you are.

 

Something I might look into is making the names of the entries shorter, e.g.

"internal/editor/textures/editor_clip", --> show: editor_clip

to reduce the width of the scroll window, and the place it on the right side of the screen. And as I noted you can keep that window open and change materials at will... nice.

 

 

Zita,

be sure to give aliasedfrog menu-based ContentHack widget a try, should my version still not work for you. I think his version is very much more what you would want. More user friendly to be able to scroll the long lists, not having to "skip" through them one by one.

Share this post


Link to post
Share on other sites

Ok just tested it yrs and not working but commands are being put in the game.cfg file. These two lines

 

bind l me_activematerial structural/dev/dev_aqua; me_activematerial structural/dev/dev_aquaddark; me_activematerial  structural/dev/dev_black; me_activematerial  structural/dev/dev_blue
 

 

bind game mousewheelup me_activematerial environment/liquids/lava/lava_burn;
 

Am using the latest version with the shouldShowHUDAE() function

 

EDIT I will re take a look tomorrow as to tired tonight and brain is starting to hurt lol

Share this post


Link to post
Share on other sites

aliasedfrog,

played around with some string manipulation, to just show the file names in the lists, not their full paths. AFAICT the file names are unique so my lookup tables should work.

 

This is a really evil hack, and probably not in the least the best way to go, but it works.

 

Added local function explode(), I prefer taking apart strings the PHP way. And create a short name array I pass to the menu. And also created a quick lookup array that lets me reassociate the short name with the full path again.

function drawScrollBox(x, y, w, h, array)
    items = contentlist;
    selection = nil

    -- PHP-like explode to take appart strings from http://lua-users.org/wiki/MakingLuaLikePhp
    local function explode(div,str) -- credit: http://richard.warburton.it
        if (div=='') then return false end
        local pos,arr = 0,{}
        -- for each divider found
        for st,sp in function() return string.find(str,div,pos,true) end do
            table.insert(arr,string.sub(str,pos,st-1)) -- Attach chars left of current divider
            pos = sp + 1 -- Jump past current divider
        end
        table.insert(arr,string.sub(str,pos)) -- Attach chars right of last divider
        return arr
    end

    -- Create an array with short entry names
    local shortarray = {}
    local lookuparray = {}
    for k, item in pairs(array) do
        local parts = explode( "/", item)         -- e.g. item = "internal/debug/brushes/midgrey"
        local short = parts[table.getn(parts)]    --> last element: midgrey
        shortarray[k] = short
        lookuparray[short] = item    --> lookuparray["midgrey"] = "internal/debug/brushes/midgrey"
    end

    selection = uiScrollSelection(shortarray, selection, x, y + UI_WINDOW_HEADER_HEIGHT, w, h - UI_WINDOW_HEADER_HEIGHT, ContentHackMenu.scrollBarData, itemHeight, uiScrollItem)
--  selection = uiScrollSelection(array, selection, x, y + UI_WINDOW_HEADER_HEIGHT, w, h - UI_WINDOW_HEADER_HEIGHT, ContentHackMenu.scrollBarData, itemHeight, uiScrollItem)
    if(selection ~= nil) then
        consolePerformCommand("me_activematerial " .. lookuparray[selection]);
--      consolePerformCommand("me_activematerial " .. selection);
    consolePrint(selection);
    end
end

This way the table width now is limited only by the 3 tabs, so the local w = 500; window width can be lowered to local w = 350; I use

ui_set_widget_anchor ContentHackMenu 1 0
ui_set_widget_offset ContentHackMenu -180.0000 0.0000

in the game.cfg.

 

 

Learning Lua:

In C all this would be ultra evil, especially since the tables shortarray and lookuparray would be recreated again and again per frame. I am not quite sure what LUA does... I read LUA at times does certain operations only once, unless something changes. From a programming point of view better solutions would interest me to understand more clearly how LUA does things.

Share this post


Link to post
Share on other sites
function drawScrollBox(x, y, w, h, array)
    items = contentlist;
    selection = nil

    -- PHP-like explode to take appart strings from http://lua-users.org/wiki/MakingLuaLikePhp
    local function explode(div,str) -- credit: http://richard.warburton.it
        if (div=='') then return false end
        local pos,arr = 0,{}
        -- for each divider found
        for st,sp in function() return string.find(str,div,pos,true) end do
            table.insert(arr,string.sub(str,pos,st-1)) -- Attach chars left of current divider
            pos = sp + 1 -- Jump past current divider
        end
        table.insert(arr,string.sub(str,pos)) -- Attach chars right of last divider
        return arr
    end

    -- Create an array with short entry names
    local shortarray = {}
    local lookuparray = {}
    for k, item in pairs(array) do
        local parts = explode( "/", item)         -- e.g. item = "internal/debug/brushes/midgrey"
        local short = parts[table.getn(parts)]    --> last element: midgrey
        shortarray[k] = short
        lookuparray[short] = item    --> lookuparray["midgrey"] = "internal/debug/brushes/midgrey"
    end

    selection = uiScrollSelection(shortarray, selection, x, y + UI_WINDOW_HEADER_HEIGHT, w, h - UI_WINDOW_HEADER_HEIGHT, ContentHackMenu.scrollBarData, itemHeight, uiScrollItem)
--  selection = uiScrollSelection(array, selection, x, y + UI_WINDOW_HEADER_HEIGHT, w, h - UI_WINDOW_HEADER_HEIGHT, ContentHackMenu.scrollBarData, itemHeight, uiScrollItem)
    if(selection ~= nil) then
        consolePerformCommand("me_activematerial " .. lookuparray[selection]);
--      consolePerformCommand("me_activematerial " .. selection);
    consolePrint(selection);
    end
end

 

 

My head is still spinning trying to read that, just to save you some code later on, if you want to shorten a string this is the easiest way i know how =)

require "base/internal/ui/reflexcore"  --prolly not even needed

indexof = {
draw = function()
	local longString = "blah/blah/blather/skite";
	
	--indexed from last occurance, searchs backwards thru strings	
	local blah = string.sub(longString, longString:match'^.*()blah', string.len(longString))
	local b = string.sub(longString, longString:match'^.*()b', string.len(longString))
	local forwardSlash = string.sub(longString, longString:match'^.*()/', string.len(longString))
	
	local forwardSlashWithOutSlash = string.sub(longString, longString:match'^.*()/' + 1, string.len(longString))
	
	nvgFontSize(40);	
	nvgFillColor(Color(255,255,255,255));
	nvgText(0,0,blah)
	nvgText(0,40,
	nvgText(0,80,forwardSlash)
	nvgText(0,120, forwardSlashWithOutSlash)
	
end
}
registerWidget("indexof")

Share this post


Link to post
Share on other sites

aliasedfrog,

thanks...

 

From reading about lua patterns yesterday I would not in my life have come up with your match() pattern. In C I would have reverse searched char by char for "/" and then used the offset in a pointer to the "rest" of the string. Times change.

 

Though I did just find out that

    local blah = string.sub(longString, longString:match'^.*()blah', string.len(longString))

can be shortened down to

    local blah = string.sub(longString, longString:match'^.*()blah', -1)

since the -1 <--> string.len(longString) are equivalent.

 

 

For anyone learning LUA as I am, trying to break down the match pattern:

match'^.*()/'
  • the ^ negates anything that follows (does not really make much sense to me)
  • . matches any char, and .* zero or more "any char"... the typical joker patter to match anything.
  • empty capture () captures the current string position (a number), important and very convenient

A test shows that to get "skite"

local longString = "blah/blah/blather/skite";
local blah = string.sub(longString, longString:match'.*()/' + 1, -1)

works just as well... the ^ is not needed. To me that makes more sense, I am surprised that using ^ works at all. Hmm... confusing.

 

I also do not see why the last occurrence of "/" is actually found and not the first one.

string.sub(longString, longString:match'.*/()', -1) 

also yields "skite". IIRC regular expressions did have a "broadest possible" interpretation of ".*", in this case that would be "blah/blah/blather" upto the last /.

 

 

Code update:

Anyway thanks to the LUA matching code, the function can be significantly shortened:

function drawScrollBox(x, y, w, h, array)
    items = contentlist;
    selection = nil

    -- Create an array with nicer short entry names
    local shortarray = {}
    local lookuparray = {}
    for k, item in pairs(array) do
        -- item e.g. "internal/debug/brushes/midgrey"
        --> last element: midgrey <-- finds last / position via ()
        local short = string.sub(item, item:match'.*()/' + 1, -1)

        shortarray[k] = short
        lookuparray[short] = item    --> lookuparray["midgrey"] = "internal/debug/brushes/midgrey"
    end

    selection = uiScrollSelection(shortarray, selection, x, y + UI_WINDOW_HEADER_HEIGHT, w, h - UI_WINDOW_HEADER_HEIGHT, ContentHackMenu.scrollBarData, itemHeight, uiScrollItem)
    if (selection ~= nil) then
        consolePerformCommand("me_activematerial " .. lookuparray[selection]);
        consolePrint(selection);
    end
end

Share this post


Link to post
Share on other sites

Interesting... the new game.cfg entries for widgets:

ui_define ContentHack =    -- text scrolling version
{
    visible = true;
}
ui_define ContentHackMenu =  -- F9 menu version
{
    offset = { x = 0.000000, y = 0.000000 };
    anchor = { x = 0, y = 0 };
    zIndex = 0.000000;
    scale = 1.000000;
}

that might change a few things when trying to get widgets to work.

Share this post


Link to post
Share on other sites

 

Code update:

Anyway thanks to the LUA matching code, the function can be significantly shortened:

function drawScrollBox(x, y, w, h, array)
    items = contentlist;
    selection = nil

    -- Create an array with nicer short entry names
    local shortarray = {}
    local lookuparray = {}
    for k, item in pairs(array) do
        -- item e.g. "internal/debug/brushes/midgrey"
        --> last element: midgrey <-- finds last / position via ()
        local short = string.sub(item, item:match'.*()/' + 1, -1)

        shortarray[k] = short
        lookuparray[short] = item    --> lookuparray["midgrey"] = "internal/debug/brushes/midgrey"
    end

    selection = uiScrollSelection(shortarray, selection, x, y + UI_WINDOW_HEADER_HEIGHT, w, h - UI_WINDOW_HEADER_HEIGHT, ContentHackMenu.scrollBarData, itemHeight, uiScrollItem)
    if (selection ~= nil) then
        consolePerformCommand("me_activematerial " .. lookuparray[selection]);
        consolePrint(selection);
    end
end

 

it's also worth noting on that, if you look up the uiSimpleItem() in reflexcore. you can create your own function (actually what i was doing before when it was offseting the list by 1 entry. i had the Y value on the text off a full row.) and drop the 2nd table of values. and just substring the value being passed into nvgDrawText(x,y, materialString)

Share this post


Link to post
Share on other sites

 

I also do not see why the last occurrence of "/" is actually found and not the first one.

string.sub(longString, longString:match'.*/()', -1) 

 

The regex ('.*/()') is the last occurrence of '/',  for first would be ('/.*()') 

Share this post


Link to post
Share on other sites

The regex ('.*/()') is the last occurrence of '/',  for first would be ('/.*()') 

 

That looks really logical... but testing on a LUA shell for Windows, I get this:

> a="internal/debug/brushes/midgrey"; print( string.sub(a, a:match'/.*()' - 10, -1) )
es/midgrey

The code is still getting the last / in the string.

> a="internal/debug/brushes/midgrey"; print( string.sub(a, a:match'/().*', -1))
debug/brushes/midgrey

This works. Trial and error reg ex testing ;).

 

Thanks for caring anyway.

Share this post


Link to post
Share on other sites

That looks really logical... but testing on a LUA shell for Windows, I get this:

> a="internal/debug/brushes/midgrey"; print( string.sub(a, a:match'/.*()' - 10, -1) )
es/midgrey

The code is still getting the last / in the string.

> a="internal/debug/brushes/midgrey"; print( string.sub(a, a:match'/().*', -1))
debug/brushes/midgrey

This works. Trial and error reg ex testing ;).

 

Thanks for caring anyway.

 

https://regex101.com/

 

for a faster way to test =)

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×