Quick Links: Download Gideros Studio | Gideros Documentation | Gideros Development Center | Gideros community chat
imGui bindings - Page 4 - Gideros Forum

imGui bindings

1246712

Comments

  • Ah, ok, so if I calculate uvs, then it will be ok.


    Another question reladed to "image" method. We could allow to pass actual Sprite objects, but in this case renderer shoud be fixed. like "IF pcmd->TextureId IS g_id then engine->bindTexture() ELSE IF pcmd->TextureId IS Sprite THEN draw sprite". What do you think?
    UVs.png
    1232 x 59 - 7K
  • hgy29hgy29 Maintainer
    Yes, you can compute the UV for TextureData (TextureBase) (0,0)-(width/exwidth,height/exheight), or take them directly from BitmapData structure (TextureRegion).

    For Sprite instead of Texture, it could be possible with a lot of restrictions and trouble: you'll have to keep refs to the sprites so that they don't get destroyed (garbage collected), they won't be part of the hierarchy from Gideros point of view, need to compute the transform matrix from imgui vertices, etc.
  • hgy29 said:

    For Sprite instead of Texture, it could be possible with a lot of restrictions and trouble: you'll have to keep refs to the sprites so that they don't get destroyed (garbage collected), they won't be part of the hierarchy from Gideros point of view, need to compute the transform matrix from imgui vertices, etc.

    Ok then :)

    I'll repeat my prev. question:

    Can I get keyboard modifiers without usign LUA?
  • hgy29hgy29 Maintainer
    rrraptor said:


    Can I get keyboard modifiers without usign LUA?

    There is a global function defined within gideros code to do that:
    int getKeyboardModifiers();
    but wether you can actually use it from a plugin is platform dependant, and I am almost sure you can't from a DLL.
    Usual way used in plugins is to invoke lua from C code, using the appliction instance, such as:
    	lua_getglobal(L,"application");
    	lua_getfield(L,-1,"getKeyboardModifiers");
    	lua_getglobal(L,"application");
    	lua_call(L,1,1);
            int modifiers=luaL_checkinteger(L,-1);
    	lua_pop(L,1);


  • hgy29 said:

    Usual way used in plugins is to invoke lua from C code, using the appliction instance, such as:

    	lua_getglobal(L,"application");
    	lua_getfield(L,-1,"getKeyboardModifiers");
    	lua_getglobal(L,"application");
    	lua_call(L,1,1);
            int modifiers=luaL_checkinteger(L,-1);
    	lua_pop(L,1);
    I know that I can do that, I was wandering if I can get it without this mess :) Alternatively, I can use luaL_dostring for that.

  • hgy29hgy29 Maintainer
    Yes, but luaL_dostring() will be much slower
  • rrraptorrrraptor Member
    edited August 8
    @keszegh @antix @SinisterSoft @totebo @talis @hgy29

    I want to ask everyone who is interested.
    ImGui changes values by passing pointer to a function. in other words, if I do that:
    float *v = 0.0f;
    ImGui::DragFloat("my slider", v)
    then value of "v" will be change by "DragFloat" function. LUA cant do that. All we can do in this situation is to return value that was changed like so:
    v = imgui:dragFloat("my slider", v)
    BUT! "DragFloat" also return "true" if value is changing RIGHT NOW ("false" otherwise), so we should also return this flag in LUA like so:
    v, active = imgui:dragFloat("my slider", v)
    There is 4 types of sliders:


    And a few more for colors.

    My question is: in what order should I return values?
    • value1, value2, value3, value4, activeFlag
      OR
    • activeFlag, value1, value2, value3, value4
      OR
    • table maybe?
    sliders.png
    705 x 426 - 24K
    slider2.png
    748 x 95 - 6K
  • keszeghkeszegh Member
    the number of values is at most 4 and always determined by the function called, right?
    in this case i vote for "value1, value2, value3, value4, activeFlag" order.
  • keszegh said:

    the number of values is at most 4 and always determined by the function called, right?
    in this case i vote for "value1, value2, value3, value4, activeFlag" order.

    Yes, they called "DragFloat", "DragFloat2", "DragFloat3", "DragFloat4" and etc.
  • hgy29hgy29 Maintainer
    I would go for doing the same as whatever is done in love2d imgui module and/or https://github.com/patrickriordan/imgui_lua_bindings.
    +1 -1 (+3 / -0 ) Share on Facebook
  • rrraptorrrraptor Member
    edited August 8
    Ive added fonts support, but they look terrible... And they dont have names.



    @hgy29 can you see whats wrong? Font loading in "initImGui".
    --API:
    local imgui = ImGui.new(application:getContentWidth(),application:getContentHeight(), {
    	-- { fontPath, fontSize, OversampleH, OversampleV, GlyphExtraSpacingX, GlyphExtraSpacingY }
    	{"Brand___.ttf", 20, 1, 1},
    	{"ARDELANEY.ttf", 20},
    	{"aliee13.ttf", 20},
    	{"cour.ttf", 20},
    })
    fonts.png
    886 x 1021 - 36K
    zip
    zip
    main_f.zip
    15K
  • talistalis Guru
    edited August 8
    In gideros lua side, there was a third parameter filtering which was antialising as far as i remembered, maybe something related with it. It is just a wild guess and nothing related with cpp code .

    https://wiki.giderosmobile.com/index.php/Font.new
  • A little resarch and came with those links:
    https://github.com/ocornut/imgui/issues/1498
    https://github.com/ocornut/imgui/issues/1065

    Friendly speaking didn't understand all as i am far away from imgui but maybe you will sort it out hence you are more experinced than me @rrraptor
  • SinisterSoftSinisterSoft Maintainer
    Re fonts: Set the filtering to 3, it's always a nice setting.

    Coder, video game industry veteran (since the '80s, ❤'s assembler), arrested - never convicted hacker (in the '90s), dad of five, he/him (if that even matters!).
    https://deluxepixel.com
  • talis said:

    In gideros lua side, there was a third parameter filtering which was antialising as far as i remembered, maybe something related with it. It is just a wild guess and nothing related with cpp code .

    https://wiki.giderosmobile.com/index.php/Font.new

    Its different with ImGui, because all fonts are "backed" into a single atlas:
    talis said:

    A little resarch and came with those links:
    https://github.com/ocornut/imgui/issues/1498
    https://github.com/ocornut/imgui/issues/1065

    Friendly speaking didn't understand all as i am far away from imgui but maybe you will sort it out hence you are more experinced than me @rrraptor

    I've already looked at these topics but I haven't found a solution. But Ive fixed names :)

    asd.png
    581 x 613 - 37K
    asd.png 36.6K
  • hgy29hgy29 Maintainer
    @rraptor, can you try to enable texture filtering (GTEXTURE_LINEAR at the end of initImGui) and see what happen ? I am a bit surprised of how the glyphs are packed in the texture, I saw in the code the oversampleH default value is 3, so I would have expected your additional glyphs to be 3x bigger in X direction in the texture itself.
  • rrraptorrrraptor Member
    edited August 10


    On the left is GTEXTURE_NEAREST, on the right - GTEXTURE_LINEAR.
    The are all 13px "Courier new" with different oversampling value (1, 2, 4 and 8).
  • rrraptorrrraptor Member
    edited August 12
    API list for now:

    ImGui:onMouseHover(event)
    ImGui:onMouseMove(event)
    ImGui:onMouseDown(event)
    ImGui:onMouseUp(event)
    ImGui:onMouseWheel(event)
     
    -- Touch inputs TODO
     
    -- Keyboard
    ImGui:onKeyUp(event)
    ImGui:onKeyDown(event)
    ImGui:onKeyChar(event)
     
    -- Input flags
    flag = ImGui:wantCaptureMouse()
    flag = ImGui:wantCaptureKeyboard()
    flag = ImGui:wantTextInput()
     
    -- Colors ???
    --ImGui:colorConvertRGBtoHSV()
    --ImGui:colorConvertHSVtoRGB()
     
    -- Styles
    ImGui:setDarkStyle()
    ImGui:setLightStyle()
    ImGui:setClassicStyle()
     
    -- Childs
    ImGui:beginChild(id, [w = 0, h = 0, borderFlag = false, ImGuiWindowFlags = 0)
    ImGui:endChild()
     
    flag = ImGui:isWindowAppearing()
    flag = ImGui:isWindowCollapsed()
    flag = ImGui:isWindowFocused([ImGuiFocusedFlags = 0])
    flag = ImGui:isWindowHovered([ImGuiHoveredFlags = 0])
    x, y = ImGui:getWindowPos()
    w, h = ImGui:getWindowSize()
    w = ImGui:getWindowWidth()
    h = ImGui:getWindowHeight()
     
    ImGui:setNextWindowPos(x, y, [ImGuiCond = 0, pivotX = 0, pivotY = 0])
    ImGui:setNextWindowSize(w, h, [ImGuiCond = 0])
    ImGui:setNextWindowContentSize(w, h)
    ImGui:setNextWindowCollapsed(flag, [ImGuiCond = 0])
    ImGui:setNextWindowFocus()
    ImGui:setNextWindowBgAlpha(alpha)
    ImGui:setWindowPos(name, x, y, [ImGuiCond = 0]) OR ImGui:setWindowPos(x, y, [ImGuiCond = 0])
    ImGui:setWindowSize(name, w, h, [ImGuiCond = 0]) OR ImGui:setWindowSize(w, h, [ImGuiCond = 0])
    ImGui:setWindowCollapsed(name, flag, [ImGuiCond = 0]) OR ImGui:setWindowCollapsed(flag, [ImGuiCond = 0])
    ImGui:setWindowFocus(name) OR ImGui:setWindowFocus()
    ImGui:setWindowFontScale(scale)
     
    scaleX, scaleY = ImGui:getContentRegionMax()
    w, h = ImGui:getContentRegionAvail()
    x, y = ImGui:getWindowContentRegionMin()
    x, y = ImGui:getWindowContentRegionMax()
    w = ImGui:getWindowContentRegionWidth()
     
    x = ImGui:getScrollX()
    y = ImGui:getScrollY()
    maxX = ImGui:getScrollMaxX()
    maxY = ImGui:getScrollMaxY()
    ImGui:setScrollX(value)
    ImGui:setScrollY(value)
    ImGui:setScrollHereX([ratio = 0.5])
    ImGui:setScrollHereY([ratio = 0.5])
    ImGui:setScrollFromPosX(x, [ratio = 0.5])
    ImGui:setScrollFromPosY(y, [ratio = 0.5])
     
    ImGui:pushStyleColor(hex, [alpha = 1])
    ImGui:popStyleColor([count = 1])
    ImGui:pushStyleVar(idx, value) OR ImGui:pushStyleVar(idx, value1, value2)
    ImGui:popStyleVar([count = 1])
    --ImGui:getStyleColorVec4()
    --ImGui:getColorU32()
    fontSize = ImGui:getFontSize()
     
    ImGui:pushItemWidth(w)
    ImGui:popItemWidth()
    ImGui:setNextItemWidth(w)
    w = ImGui:calcItemWidth()
    ImGui:pushTextWrapPos([localX = 0])
    ImGui:popTextWrapPos()
    ImGui:pushAllowKeyboardFocus(flag)
    ImGui:popAllowKeyboardFocus()
    ImGui:pushButtonRepeat(flag)
    ImGui:popButtonRepeat()
     
    ImGui:separator()
    ImGui:sameLine([offsetX = 0, spacing = -1])
    ImGui:newLine()
    ImGui:spacing()
    ImGui:dummy(w, h)
    ImGui:indent([indent = 0])
    ImGui:unindent([indent = 0])
    ImGui:beginGroup()
    ImGui:endGroup()
     
    x, y = ImGui:getCursorPos()
    x = ImGui:getCursorPosX()
    y = ImGui:getCursorPosY()
    x, y = ImGui:getCursorStartPos()
    x, y = ImGui:getCursorScreenPos()
    ImGui:alignTextToFramePadding()
    lineH = ImGui:getTextLineHeight()
    lineH = ImGui:getTextLineHeightWithSpacing()
    frameH = ImGui:getFrameHeight()
    frameH = ImGui:getFrameHeightWithSpacing()
     
    ImGui:pushSID(strID) OR ImGui:pushSID(strBegin, strEnd)
    ImGui:pushNID(id)
    ImGui:popID()
    ImGui:getSID(strBegin, strEnd)
     
    ImGui:textUnformatted(text, [textEnd])
    ImGui:text(text)
    ImGui:textColored(text, hex, [alpha = 1])
    ImGui:textDisabled(text)
    ImGui:textWrapped(text)
    ImGui:labelText(text, label)
    ImGui:bulletText(text)
     
    pressFlag = ImGui:button(text, [w = 0, h = 0])
    pressFlag = ImGui:smallButton(text)
    pressFlag = ImGui:invisibleButton(stringID, [w = 0, h = 0])
    pressFlag = ImGui:arrowButton(stringID, [ImGuiDir = 0])
    ImGui:image(texture, w, h, [tintColor = 0xffffff, tintAlpha = 1, borderColor = 0xffffff, borderAlpha = 0, uv1x = 1, uv1y = 1, uv0x = 0, uv0y = 0])
    pressFlag = ImGui:imageButton(texture, w, h, [padding = -1, tintColor = 0xffffff, tintAlpha = 1, borderColor = 0xffffff, borderAlpha = 0, uv1x = 1, uv1y = 1, uv0x = 0, uv0y = 0])
    pressFlag = ImGui:checkbox(text, flag)
    ImGui:checkboxFlags(label, ) -- TODO
    pressFlag = ImGui:radioButton(text, flag)
    ImGui:progressBar(fraction, [anchorX = -1, anchorY = 0, overlayString = nil])
    ImGui:bullet()
    openFlag = ImGui:beginCombo(text, previewText, [ImGuiComboFlags = 0])
    ImGui:endCombo()
    currentItem, isOpen = ImGui:combo(label, currentItem, items) -- items (table): {"item1", "item2", ...}
     
    value, isDragingFlag = ImGui:dragFloat(label, value, [incStep = 1, min = 0, max = 0, formatString = "%.3f", power = 1])
    value1, value2, isDragingFlag = ImGui:dragFloat2(label, value1, value2, [incStep = 1, min = 0, max = 0, formatString = "%.3f", power = 1])
    value1, value2, value3, isDragingFlag = ImGui:dragFloat3(label, value1, value2, value3, [incStep = 1, min = 0, max = 0, formatString = "%.3f", power = 1])
    value1, value2, value3, value4, isDragingFlag = ImGui:dragFloat4(label, value1, value2, value3, value4, [incStep = 1, min = 0, max = 0, formatString = "%.3f", power = 1])
    valueMin, valueMax, isDragingFlag = ImGui:dragFloatRange2(label, valueMin, valueMax, [incStep = 1, min = 0, max = 0, formatMinString = "%.3f", formatMaxString = formatMinString, power = 1])
     
    value, isDragingFlag = ImGui:dragInt(label, value, [incStep = 1, min = 0, max = 0, formatString = "%d"])
    value1, value2, isDragingFlag = ImGui:dragInt2(label, value1, value2, [incStep = 1, min = 0, max = 0, formatString = "%d"])
    value1, value2, value3, isDragingFlag = ImGui:dragInt3(label, value1, value2, value3, [incStep = 1, min = 0, max = 0, formatString = "%d"])
    value1, value2, value3, value4, isDragingFlag = ImGui:dragInt4(label, value1, value2, value3, value4, [incStep = 1, min = 0, max = 0, formatString = "%d"])
    ImGui:dragIntRange2(label, )
    ImGui:dragScalar()
     
    value, isDragingFlag = ImGui:sliderFloat(label, value, [incStep = 1, min = 0, max = 0, formatString = "%.3f", power = 1])
    value1, value2, isDragingFlag = ImGui:sliderFloat2(label, value1, value2, [incStep = 1, min = 0, max = 0, formatString = "%.3f", power = 1])
    value1, value2, value3, isDragingFlag = ImGui:sliderFloat3(label, value1, value2, value3, [incStep = 1, min = 0, max = 0, formatString = "%.3f", power = 1])
    value1, value2, value3, value4, isDragingFlag = ImGui:sliderFloat4(label, value1, value2, value3, value4, [incStep = 1, min = 0, max = 0, formatString = "%.3f", power = 1])
    valueInRad, isDragingFlag = ImGui:sliderAngle(label, valueInRad, [min_degrees = -360, max_degrees = 360, formatString = "%.0f deg"])
    value, isDragingFlag = ImGui:sliderInt(label, value, [incStep = 1, min = 0, max = 0, formatString = "%d"])
    value1, value2, isDragingFlag = ImGui:sliderInt2(label, value1, value2, [incStep = 1, min = 0, max = 0, formatString = "%d"])
    value1, value2, value3, isDragingFlag = ImGui:sliderInt3(label, value1, value2, value3, [incStep = 1, min = 0, max = 0, formatString = "%d"])
    value1, value2, value3, value4, isDragingFlag = ImGui:sliderInt4(label, value1, value2, value3, value4, [incStep = 1, min = 0, max = 0, formatString = "%d"])
    value, isDragingFlag = ImGui:sliderScalar(label, ImGuiDataType, value, [min = nil, max = nil, formatString = nil])
    value, isDragingFlag = ImGui:vSliderFloat(label, w, h, value, min, max, [formatString = "%.3f", power = 1])
    value, isDragingFlag = ImGui:vSliderInt(label, w, h, value, min, max, [formatString = "%d"])
    value, isDragingFlag = ImGui:vSliderScalar(label, w, h, ImGuiDataType, [min = nil, max = nil, formatString = nil, power = 1])
     
    -- WIP
    text, isTypingFlag = ImGui:inputText(label, initialText, [ImGuiInputTextFlags = 0])
    --ImGui:InputTextMultiline()
    --ImGui:InputTextWithHint()
    --ImGui:InputFloat()
    --ImGui:InputFloat2()
    --ImGui:InputFloat3()
    --ImGui:InputFloat4()
    --ImGui:InputInt()
    --ImGui:InputInt2()
    --ImGui:InputInt3()
    --ImGui:InputInt4()
    --ImGui:InputDouble()
    --ImGui:InputScalar()
     
    -- Colors
    hexColor, isTouchingFlag = ImGui:colorEdit3(label, hexColor, [ImGuiColorEditFlags = 0])
    hexColor, alpha, isTouchingFlag = ImGui:colorEdit4(label, hexColor, [alpha = 1, ImGuiColorEditFlags = 0])
    hexColor, isTouchingFlag = ImGui:colorPicker3(label, hexColor, [ImGuiColorEditFlags = 0])
    hexColor, alpha, originalColor, originalAlpha, isTouchingFlag = ImGui:colorPicker4(label, hexColor, [alpha = 1, originalColor = 0xffffff, originalAlpha = 1, ImGuiColorEditFlags = 0])
    isHoveringFlag = ImGui:colorButton(stringID, hexColor, [alpha = 1, ImGuiColorEditFlags = 0, w = 0, h = 0])
    ImGui:setColorEditOptions(ImGuiColorEditFlags)
     
    -- Windows
    isOpenFlag = ImGui:beginWindow()
    ImGui:endWindow()
     
    -- Render
    ImGui:newFrame()
    ImGui:render()
    ImGui:endFrame()
     
    -- Display size
    ImGui:setDisplaySize(x, y)
    ImGui:setDisplayScale(x, y)
     
    -- Demos
    isOpenFlag = ImGui:showUserGuide()
    isOpenFlag = ImGui:showDemoWindow()
    isOpenFlag = ImGui:showAboutWindow()
    isOpenFlag = ImGui:showStyleEditor()
    isOpenFlag = ImGui:showFontSelector()
    isOpenFlag = ImGui:showMetricsWindow()
    isOpenFlag = ImGui:showStyleSelector()
    isOpenFlag = ImGui:showLuaStack()


    Color format is different from ImGui original. It is gideros like: 0xaabbcc, alpha. Alpha is optional and by default is 1.
    +1 -1 (+4 / -0 ) Share on Facebook
  • hgy29hgy29 Maintainer
    Great job @rraptor! Now Gideros has several GUI options.

    Likes: SinisterSoft

    +1 -1 (+1 / -0 ) Share on Facebook
  • Thanks, iam really intrigued if imgui is versatile enough to convert my gui to it. Eg. My buttons have long click capability, can I do that with imgui?
  • rrraptorrrraptor Member
    edited August 12
    keszegh said:

    Edit: multiple post, sorry.

    I guess ImGui does not have this abilty out of the box, so I did this:
    imgui:button("my button") -- can be any windget
    if (imgui:isItemHovered()) then 
    	local seconds = imgui:mouseDownSec(KeyCode.MOUSE_LEFT)
    	if (seconds > 0) then 
    		-- holding button
    	end
    end
    And it works :)

    I can make it into a native function if you want :)
  • Thanks, great, no need for native function, I can do the same. Rather add the official ones. And can't wait to try these in next gideros release. Awesome.

    Likes: MoKaLux

    +1 -1 (+1 / -0 ) Share on Facebook
  • rrraptorrrraptor Member
    edited August 12
    @keszegh
    I just found out this:

    :smiley:

    Basically its that simple:
    imgui:pushButtonRepeat(true)
    -- any button related code
    imgui:popButtonRepeat()

    Likes: MoKaLux

    holdButton.gif
    587 x 269 - 120K
    +1 -1 (+1 / -0 ) Share on Facebook
  • rrraptorrrraptor Member
    edited August 12
    @hgy29 question for you :)
    How to correctly pass array to "Combo" or any other function that accepts "const ANY_TYPE* items[]"? I kinda know how to work with "const ANY_TYPE* items" but not with this one...
    bool ImGui::Combo(const char* label, int* current_item, const char* const items[], int items_count, int height_in_items)
    bool ImGui::Combo(const char* label, int* current_item, const char* items_separated_by_zeros, int height_in_items)
    I have this:
    int ImGui_impl_Combo(lua_State *L)
    {
        const char* label = luaL_checkstring(L, 2);
        int item_current = luaL_checkinteger(L, 3);
     
        luaL_checktype(L, 4, LUA_TTABLE);
        size_t len = lua_objlen(L, 4);
        const char* items[len];
        lua_pushvalue(L, 4);
        lua_pushnil(L);
        while (lua_next(L, -2))
        {
            lua_pushvalue(L, -2);
            int index = lua_tointeger(L, -1);
            const char *str = lua_tostring(L, -2);
            items[index] = str;
            lua_pop(L, 2);
        }
        lua_pop(L, 1);
     
        bool result = ImGui::Combo(label, &item_current, items, len); // crash here
     
        lua_pushnumber(L, item_current);
        lua_pushboolean(L, result);
        free(items); 
        return 2;
    }
    But it does not work. Btw,
    hgy29 said:

    Something like:

    #include "glog.h" //From gideros SDK
    #define IM_ASSERT( exp ) \
        ( (exp) ? (void)0 : glog_v("Failed assertion at %s:%d %s\n",  __FILE__,__LINE__, #exp))
    Log will be sent to the debugger. If you are on windows, you can use DebugView to see them without a debugger.
    does not work either, so I dont know why it crashes...
  • hgy29hgy29 Maintainer
    A few things that may/will go wrong with the code above:
    - you assume that the item array given from lua has numerical keys (length returned by lua_objlen), but you traverse it as a generic table, with lua_next. You should use lua_rawgeti instead of lua_next in that case.
    - items array (C side) is allocated on stack, but freeed as if dynamically allocated. You don't need to 'free()' it when allocated on stack
  • rrraptorrrraptor Member
    edited August 13
    hgy29 said:

    A few things that may/will go wrong with the code above:
    - you assume that the item array given from lua has numerical keys (length returned by lua_objlen), but you traverse it as a generic table, with lua_next. You should use lua_rawgeti instead of lua_next in that case.

    But technicaly I still can use lua_next, right? :D

    Now it works :)
    int ImGui_impl_Combo(lua_State *L)
    {
        luaL_checktype(L, 4, LUA_TTABLE);
        size_t len = luaL_getn(L, 4);
        if (len == 0)
            return 0;
     
        const char* label = luaL_checkstring(L, 2);
        int item_current = luaL_checkinteger(L, 3);
        const char* items[len];
        lua_pushvalue(L, 4);
        for (int i = 0; i < len; i++)
        {
            lua_rawgeti(L, 4, i+1);
            const char* str = lua_tostring(L,-1);
            items[i] = str;
            lua_pop(L, 1);
        }
        lua_pop(L, 1);
     
        bool result = ImGui::Combo(label, &item_current, items, len);
     
        lua_pushnumber(L, item_current);
        lua_pushboolean(L, result);
        return 2;
    }
    hgy29 said:

    - items array (C side) is allocated on stack, but freeed as if dynamically allocated. You don't need to 'free()' it when allocated on stack

    Ah, ok, good to know.
  • rrraptorrrraptor Member
    edited August 13


    @hgy29 I used same font as on wiki page and UVs are different? (on the left is original image)
    123.png
    1319 x 715 - 94K
    123.png 94.1K
  • @rrraptor if you share here or in pm your paypal friend account, then i'd be happy to donate some to show my gratitude. thanks for your work.

    Likes: MoKaLux

    +1 -1 (+1 / -0 ) Share on Facebook
Sign In or Register to comment.