[Mod] Smart Formspecs - OO builder + binding [1.1][smartfs]

User avatar
rubenwardy
Moderator
Posts: 6107
Joined: Tue Jun 12, 2012 18:11
GitHub: rubenwardy
IRC: rubenwardy
In-game: rubenwardy
Location: United Kingdom
Contact:

by rubenwardy » Post

domtron vox wrote:

Code: Select all

dofile(minetest.get_modpath(minetest.get_current_modname()).."/smartfs.lua")

minetest.register_on_joinplayer(function(player)

    local form = smartfs.create("test",
                   function(state)

                       state:size(8,8)

                       --set variable using creation assignment
                       local button1 = state:button(0,0, 2,1, "btn1","A button")
                  
                       --set variable using state:get
                       state:button(2,0, 3,1, "btn2","Another button")
                       local button2 = state:get("btn2")

                       --incremented so each new label is in the right spot
                       local ypos1 = 2
                       local ypos2 = 2
                       
                       --button one on clicked function
                       state:get("btn1"):onClick(function(self, state)
                           state:label(0,ypos1, "lable1"..ypos1, "A label!")
                           ypos1 = ypos1 + 1
                       end)

                       --button two on clicked function
                       button2:onClick(function(self, state)
                           state:label(2,ypos2, "lable2"..ypos2, "A label!")
                           ypos2 = ypos2 + 1
                       end)                       


                   end)

    form:show(player:get_player_name())

end)
Smartfs.create should be used like minetest.register_node.

That may just be a simple example, but if two players logged in, it would crash.
Last edited by rubenwardy on Tue Mar 04, 2014 17:44, edited 1 time in total.

User avatar
rubenwardy
Moderator
Posts: 6107
Joined: Tue Jun 12, 2012 18:11
GitHub: rubenwardy
IRC: rubenwardy
In-game: rubenwardy
Location: United Kingdom
Contact:

by rubenwardy » Post

Dynamic forms added

Dynamic forms allow you to make a form without having to register it while the game is loading.

Code: Select all

local state = smartfs.dynamic("smartfs:dyn_form", name)
state:load(minetest.get_modpath("smartfs").."/example.smartfs")
state:get("btn"):click(function(self,state)
    print("Button clicked!")
end)
state:show()

Make sure you call state:show()

Other changes

  • Fixed some inventory stuff.
  • Creating forms after the game loads is not allowed, and will trigger an crash.

Documentation

ReadMe (must read) - Full Api Listing
Last edited by rubenwardy on Tue Mar 04, 2014 17:57, edited 1 time in total.

User avatar
domtron vox
Member
Posts: 111
Joined: Thu Feb 20, 2014 21:07
GitHub: DomtronVox
IRC: Domtron
In-game: Domtron

by domtron vox » Post

Simple fix

Code: Select all

line 6  local form = smartfs.create("test@"..player:get_player_name(),
I had assumed that later forms with the same name as previous forms would just overwrite the previous forms. I edited my previous post so as to not lead others astray. ;)

User avatar
rubenwardy
Moderator
Posts: 6107
Joined: Tue Jun 12, 2012 18:11
GitHub: rubenwardy
IRC: rubenwardy
In-game: rubenwardy
Location: United Kingdom
Contact:

by rubenwardy » Post

domtron vox wrote:Simple fix

Code: Select all

line 6  local form = smartfs.create("test@"..player:get_player_name(),
I had assumed that later forms with the same name as previous forms would just overwrite the previous forms. I edited my previous post so as to not lead others astray. ;)
It should be like this:

Code: Select all

dofile(minetest.get_modpath(minetest.get_current_modname()).."/smartfs.lua")

local form = smartfs.create("modname:test",function(state)
    state:size(8,8)

    --set variable using creation assignment
    local button1 = state:button(0,0, 2,1, "btn1","A button")
                  
    --set variable using state:get
    state:button(2,0, 3,1, "btn2","Another button")
    local button2 = state:get("btn2")

    --incremented so each new label is in the right spot
    local ypos1 = 2
    local ypos2 = 2
                       
    --button one on clicked function
    state:get("btn1"):onClick(function(self, state)
        state:label(0,ypos1, "lable1"..ypos1, "A label!")
        ypos1 = ypos1 + 1
    end)

    --button two on clicked function
    button2:onClick(function(self, state)
        state:label(2,ypos2, "lable2"..ypos2, "A label!")
        ypos2 = ypos2 + 1
    end)                   
end)

minetest.register_on_joinplayer(function(player)
    form:show(player:get_player_name())
end)
If you need to get the name of the player, state.player is the player name.

You can also supply parameters:

Code: Select all

form:show(playername,{some="params"})

if (state.param.some == "params")
    print("yay!")
Last edited by rubenwardy on Tue Mar 04, 2014 17:55, edited 1 time in total.

User avatar
domtron vox
Member
Posts: 111
Joined: Thu Feb 20, 2014 21:07
GitHub: DomtronVox
IRC: Domtron
In-game: Domtron

by domtron vox » Post

I have been very busy with RL but just got some time to write up a list element. It is mostly functional but I'm sure it could use some improving. I just expanded on the example code I wrote earlier to develop/test it. I have an error i don't understand when running close() on the form in the double click function. The form closes but another form pops up with the text "formspec closing not yet created."

As always you can keep it or discard it at your discretion. This code has not been tested on a server yet.

Code: Select all

dofile(minetest.get_modpath(minetest.get_current_modname()).."/smartfs.lua")

local form = smartfs.create("smartfs_test:test", function(state)
    state:size(8,8)

    --set variable using creation assignment
    local button1 = state:button(0,0, 2,1, "btn1","A button")
                  
    --set variable using state:get
    local button2 = state:button(3,0, 3,1, "btn2","Another button")
                       
              
    --lists to hold values
    local lst1 = mymod_constructors.list(state, 0,2, 3,4, "list1")
    local lst2 = mymod_constructors.list(state, 4,2, 3,4, "list2")
                    
    lst1:onClick(function(self, state, index)
        print("click")
        print(index)
    end)
    lst1:onDoubleClick(function(self, state, index)
        print("Dclick")
        print(index)
        state:close()
    end)
                       
    --button one on clicked function
    state:get("btn1"):onClick(function(self, state)
        lst1:addItem("A label!")
    end)

    --button two on clicked function
    button2:onClick(function(self, state)
        lst2:addItem("A label!")
    end)                       


end)

minetest.register_on_joinplayer(function(player)
    form:show(player:get_player_name())
end)

mymod_constructors ={
    list = function(state, x,y,w,h,name)
        return state:element("list", {pos={x=x,y=y}, size={w=w,h=h}, name=name, items={}})
    end
}

smartfs.element("list",{
        build = function(self)
                local listformspec = "textlist["..
                                     self.data.pos.x..","..self.data.pos.y..
                                     ";"..
                                     self.data.size.w..","..self.data.size.h..
                                     ";"..
                                     self.name..
                                     ";"

                --loop through the list's items and add them to the formspec
                for i,value in ipairs(self.data.items) do
                    listformspec = listformspec..value..","
                end
                listformspec = string.sub(listformspec, 0, -2) --removes extra ,
                --close out the list items section
                listformspec = listformspec..";"
                
                --TODO support selected idx and transparency 

                --close formspec definition and return formspec
                listformspec = listformspec.."]"
                return listformspec
        end,

        submit = function(self,fields)
                if fields[self.name] then
                    local _type = string.sub(fields[self.data.name],1,3)
                    local index = string.sub(fields[self.data.name],5)
                    if _type == "CHG" and self._click then
                        self:_click(self.root, index)
                    elseif _type == "DCL" and self._doubleClick then
                        self:_doubleClick(self.root, index)
                    end
                end
        end,
        onClick = function(self, func)
                self._click = func
        end,
        onDoubleClick = function(self, func)
                self._doubleClick = func
        end,
        setPosition = function(self,x,y)
        self.data.pos = {x=x,y=y}
    end,
    getPosition = function(self,x,y)
        return self.data.pos
    end,
    setSize = function(self,w,h)
        self.data.size = {w=w,h=h}
    end,
    getSize = function(self,x,y)
        return self.data.size
    end,
        --adds an item to the end of the list
        --TODO allow an optional pos argument to be passed
        addItem = function(self, item)
                table.insert(self.data.items, item)
        end,
        --Deletes the last item of the list
        --TODO allow an optional pos argument to be passed
        removeItem = function(self)
                table.remove(self.data.items)
        end,
        --removes the last item and returns it
        popItem = function(self)
                local item = self.data.items[#self.data.items]
                table.remove(self.data.items)
                return item
        end
})

User avatar
rubenwardy
Moderator
Posts: 6107
Joined: Tue Jun 12, 2012 18:11
GitHub: rubenwardy
IRC: rubenwardy
In-game: rubenwardy
Location: United Kingdom
Contact:

by rubenwardy » Post

The Minetest API does not support closing a formspec remotely, so state:close() has nothing to call.

Well done with that element, I will add it to the main mod. Thank you.

User avatar
christoferlevich
Member
Posts: 324
Joined: Thu Dec 01, 2016 23:44
GitHub: ChristoferL
Location: Athol, Massachusetts

Re: [Mod] Smart Formspecs - OO builder + binding [1.1][smart

by christoferlevich » Post

I want to do something so easy its stupid, and looking for a mod to manage this might be overkill, and this mod may or may not be the perfect choice, so let me just ask this... I want to create a pop up formspec students use to 'mark' their homes, land, shops, etc.

The idea would be - punch a node, formspec pops, close form spec. In the formspec, all I want is a custom png file we (the students and I) generate off of files we build outside of minetest. I figure all I need is png set as the 'background' image, and then all I would need is the the close button.

This way I can give the students a reason to learn other programs like gimp and inkscape, ultimately laying out their creations in Scribus, exported as pdfs then converted to png created for Minetest entry where they will learn to create their own 'node'. My classes start Thurs., 10.4.2017, but I have some time before I need to approach this in class. Any thoughts are welcome.

I am finding the more they can personalize IN the game, the more invested they become.
everything can be a learning experience...

Post Reply

Who is online

Users browsing this forum: No registered users and 4 guests