Coder Social home page Coder Social logo

domy's People

Contributors

karai17 avatar shakesoda avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Forkers

antoniomoder

domy's Issues

Batching UI elements

Batching elements is going to be key to efficiently drawing. If we have hundreds or thousands of individual elements, we sure don't want to draw them one at a time.

Since each element may have a relatively unique texture, it is going to be crucial to create texture atlases so we can batch as many elements together as possible.

With a large texture atlas, we can then sort all of the elements based on their Z-index position. All root elements will have a default Z-index based on their sequential order, starting from 1. All child elements will have a Z-index of parent.properties.z-index + 1 unless manually set.

Once every element is sorted by their Z-index, the elements will be buffered into a sprite batch and drawn.

On the next frame, if there are any updates, the batch will be resorted before being drawn again, et infinitum.

Does this sound right? Am I missing anything?

on_mouse_over

If you wanna show tooltips this is important.

Only using enter and leave does not work in love2d, because they are only called when window is active.

Text input

Well text input in love is kinda hard, but I made an almost full text editor so it is not THAT hard haha.

Check it out, it is messy (I wrote it in a day) but it haves the functions you may need.

Missing features are copying, cutting, pasting, undo, redo, and that is it I think.

You may need to refactor everything, but I can always help

Finding the elements

As we discussed in issue #8 and #4 a problem is getting the elements that should be modified.

How should be the lookup tables be structured? How can we get an element filtered by id and classes and type and node.... etc.

This algorithm should also be efficient

GUI Widgets

The general idea here is to be able to define a sort of GUI "class" that can be used extensively. A great example would be building a generic name plate widget complete with avatar, name, health bar, etc. The widget can be used for the player, party members, targeted enemy, etc.

This feature is an absolute must.

3D GUIs

While this may not exactly be important for LOVE proper, I am working on a LOVE3D project and would like for this to support both 2D and 3D GUIs. More thought needs to be put into 3D GUIs, so if you have any ideas, toss them here. :)

Small documentation suggestions

I think this line needs to be a bit more explicit what exactly to "require". Many libraries have a single file which needs to required so I think the DOMy documentation should say something like "require the folder in which the init.lua file is located".

EDIT: And maybe a link to the documentation should be added to README.md.

EDIT2: Small typo in this line " The model is used to structure the interface and nothing more." and this one "working horse of ..."

Some thoughts on the Script API

The Script API should vaguely resemble jQuery (but be less convoluted). Each object should have:

  • an id
  • a parent
  • a list of siblings
  • a list of children
  • a list of properties
  • a list of classes
  • a set of event callbacks

And probably other stuff, too.

The lists of siblings and children should be indexed arrays (you can loop through them via ipairs).

The parent, siblings, and children should be pointers to other objects.

There should be helper functions in place despite Lua's ability to access data directly.

local child = object.children[3] -- object
local other_child = object:get_child(3) -- object

Customized properties (properties not set by the object default, id, or class associated to an object) should be held in a custom properties table so when an object needs to be rerendered (say, if it is resized), the programatically defined properties will persist.

If anyone else has ideas, feel free to throw them in here and we can discuss them.

Cloning Elements

I am currently implementing the base Element object and I need to know what people would expect from a cloned element.

When cloning an Element, do you simply expect a default element of the same type with the same value, an element with the same value and properties (such as visual styles) and scripts, or something else?

My issue with cloning properties verbatim is that some properties such as positioning are going to be relative (unless otherwise specified) so if you clone an element that is 10 dp to the left and it was inside some other element, this new element will be 10 dp left from the screen which is not in the same position at all. Is that expected behaviour?

Markup Syntax

What does everyone think about the markup syntax? I want the markup to be Lua so I don't need to run a script to convert, say, XML to Lua when it's not necessary. Is the current markup.lua example sensible or are there some serious changes needed?

The basis here is that named named keys within a table are used to define the object and its properties while the sequential keys are used to define child objects (if tables) or direct value (if string/float). Maybe value="some value" would be less ambiguous, if not more wordy?

{ type="block", id="windows",
    { type="text", "Windows XP+" } ,
    { type="list",
        { type="text", class="link", onclick=web_link(strings.some_link), "32-bit installer" },
        { type="text", class="link", onclick=web_link(strings.some_link), "32-bit zipped" },
        { type="text", class="link", onclick=web_link(strings.some_link), "64-bit installer" },
        { type="text", class="link", onclick=web_link(strings.some_link), "64-bit zipped" },
    },
}

Draw Stack

After discussing the idea of ordering, buffering, and drawing elements, I think the following system may be wise:

  1. A draw stack within the GUI instance is created using root elements as a base
  2. Elements will have a bring_forward() and send_behind() function set that re-positions them within the draw stack
  3. the aforementioned functions will take a single argument that allows you to determine the offset where you want to place the element within the stack
    • send_back(1) places the element after the first item in the stack
    • bring_forward(1) places the element before the last item in the stack
    • This will allow people to have "always behind" and "always on top" elements such as quest trackers and action bars, respectively
  4. If the element in which the function is called is not a root element (and therefore has a parent), it will push the request up the family hierarchy until the root is reached
  5. Detaching an element from a family makes the element a root element, therefore it is put into the draw stack (at the end, so it is drawn on top)
  6. Attaching an element to a family will do the opposite--remove the element from the draw stack

Some example uses:

local frame = gui:new_element("frame")
function frame:on_focus()
    self:bring_forward() -- no arg defaults to draw on top
    -- do frame stuff
end
local frame = gui:new_element("frame")
local button = gui:new_element("button", frame)
function button:on_focus()
    self:bring_forward(1) -- never draw over top of the action bar!
                          -- also pushes the command up to frame
    -- do button stuff
end

I think this could work pretty well and give designers enough control without forcing them to manage their own z-index table. Thoughts?

[Markup] Value Key

Should there be a value key, or should value (and sometimes children) simply be the sequential second key? Or perhaps both, with value overriding a sequential value?

-- value key
{ "text", value="Some text", id="important_textbox", class={"class1", "class2"},
    { "text", value="Some child" },
}

-- sequential key
{ "text", "Some text", id="important_textbox", class={"class1", "class2"},
    { "text", "Some child" },
}

-- priority key
{ "text", "Some text", value="This takes priority!", id="important_textbox", class={"class1", "class2"},
    { "text", "Some child" },
}

Styles Syntax

What is the community's opinion of the current styles syntax? The way I have designed it is to organize various scopes since Lua does not have symbols like CSS. The way that this would work would be that for every instance of an object type, the parser will check the styles or see if any styles are defined and apply them. The parser will then check if there is an ID, and if there is a style for that ID. Any ID styles will override Object styles. Finally the parser will check classes (in the order given) and apply them.

Default->Object_Style->ID_Style->Class1_Style->Class2_Style->Class3_Style->...

The properties are mostly stolen from CSS though I plan to review them and make them more game oriented and less document oriented.

I am unsure if I should enforce ID styles tot he first instance of an ID (as an ID should be unique) or just enforce IDs in scripting.

Image replacements for unicode glyphs! My emoji is the emoji that will emote all the ji's.

Defining directional input for an irregular grid

In a regular grid, you have very obvious up, down, left, and right directions. When taking input from a user, it is very clear which cell within the grid they want to highlight.

In an irregular grid, this is not always obvious. An irregular grid can be defined as a group of sibling objects that are in an unstructured positioning scheme such that the items have no defined path between them. This makes determining if "left" input from object A is expected to go to object B or object C.

What I propose is a sort of constellation system where a set of objects are are handed to the parser and the parser spits out what up, down, left, and right means for each object.

As you can see from the above image, each Star object has a path to nearby objects. In this example, the maximum paths seem to be three, but for a GUI system I believe we can have a maximum of four.

So my question is this: What sort of data should the parser require? I suggest that a table of objects, a maximum radius for paths, and maybe more?

-- in this example, each obj has at minimum an X any Y coordinate
-- units of measurement are listed in dp, not px
local objects = { obj1, obj2, onj3, obj4, obj5 }
local radius = 5
local grid = dom.get_constellation(objects, radius)

Hypertext

How are we going to pull off hypertext? The ability to use multiple colours, fonts, throw in some emoji, etc in a single line or paragraph of text is probably going to be important, especially for online games with chat boxes.

Anchor Points

It was suggested in the forum thread that anchor points for elements would be wise. An archor point is defined as the point of an element where positioning takes place. For instance, by default anchor points would be Top-Left, or 0,0. If I want to position an element at 0.5,0.0 on screen, then the top-left corner of the element will be in the middle of the screen on the x axis. If the anchor point is Top-Right or 1,0, then the top-right corner will be at the 50% mark.

The most notable use case for this is allowing elements to resize in any desired direction. If you set the anchor to the centre of the object, then when you resize the object it will stay where it is located but grow or shrink outward. If you set the anchor point of an object to the bottom centre, then you can grow or shrink an object to the edge of the screen.

So I guess the question here is, should there be a set of defined anchor points (TL, TC, TR, L, C, R, BL, BC, BR) or should the anchor be definable based on a % value? vec2(0.25,0.78) would set the anchor point to 25% from the left and 78% from the top.

Element Focus

The GUI instance needs to be aware which element currently has focus.

Each element needs the following functions:

  • focus(bool)
    • Set this element to have input focus
    • Call the on_focus callback
  • has_focus()
    • return whether or not this element has focus
function Element:focus(f)
    local focus = self:has_focus()
    if focus and not f then
        gui:set_focus(false)
    elseif not focus and f then
        gui:set_focus(self)
    end
end

function Element:has_focus()
    return gui._focus == self
end

I suppose for this to work, each element is going to need a handle of the GUI instance it belongs to!

Draw to Tiled Canvas

Okay so here is the basic idea:

  • Divide canvas into a grid
  • Determine which cell(s) an element belongs to at any given time
  • If any changes occur to an element, declare the cell(s) invalid
  • Redraw any invalid cells

Anything that could affect the visual status of a cell would make it invalid, such as an animation, an element moving, an element scrolling, etc etc etc.

Event Markup

As discussed in Issue #4, should events such as on_click, on_hover, etc be able to be defined within the markup of the file, or should events be strictly defined in scripts?

{ "button" on_click=function() do_a_thing() end, "Button Text" }

or

-- markup.lua
{ "button", id="Button1", "Button Text" }

-- scripts.lua
local button = dom.get_button_by_id("Button1")
button.on_click = do_a_thing

Coordinate System

My feeling is that we should toss the idea of pixels right out the window. All objects should have their own local coordinate system, both X and Y valued from 0 to 1. This will allow consistent spacing and positioning across all screens.

This may also bring an issue where persons with box screens (4:3, 5:4) may have skinny GUIs or persons with wide screens (16:9, 16:10) may have fat GUIs depending on how the GUI designer is putting things together. A fix for this may be to use a Point (pt) system where an object can be set to a fixed size based on more relevant metrics than pixels. I believe Android and CSS both allow for various point systems such as pt, em, ex, and px on top of the % system.

EDIT:

We will be going with %, dp, and sp units.

local w, h = love.graphics.getDimensions()
local pc_w = value * w -- value is between 0 and 1
local pc_h = value * h
local dp = px * love.window.getPixelScale()
local sp = dp * font_scale

http://stackoverflow.com/questions/2025282/difference-between-px-dp-dip-and-sp-in-android

http://blog.edwinevans.me/?p=131

http://developer.android.com/guide/practices/screens_support.html

Batching Elements

So I have decided to use a SpriteBatch for each individual family tree. A family tree is defined as having a root element with no parent.

I will be using a Canvas as the texture for the batches (maybe a canvas for each batch, but I can probably get away with a single texture).

I will draw each object to the canvas on init, and use scissors to select objects to clear when a style needs to be changed (such as for animations, deletions, interactions, etc).

This method should allow me to render all objects to look exactly as expected while maintaining the efficiency of batching draw calls since every single object will not need to be updated every single frame.

Explicit type

In the markup you declare the type o each segment or child like this:

{type="header",id="myHeader",
    {type="image",id="HeaderIcon",src="pathToMyImage"}
    ...
}

I think that it may be better to have the type mandatory being the first element:

{"header",id="myHeader",
    {"image",id="HeaderIcon",src="pathToMyImage"}
    ...
}

It looks more like HTML, also you avoid writing type at every node hahaha

Image Repeat

You could use Image:setWrap() and a Quad bigger than the image to make it repeat.

Naming Convention

Just wanted to say it... I hate variables that look like this_because_they_are_not_cool hahaha. My point of view. I just hate writing things that dont add to the content or readability of the code

Widget API

A Widget is a predefined GUI object that can be loaded into any GUI instance. A simple example would be a Window Frame that includes a close button, a collapse button, a title area, and a content area. The Window Frame would have predefined styles and scripts. Once a widget is loaded, you can load it like any other element.

My basic idea for the Widget API is as follows:

  1. Define a Widget Directory for the GUI instance (default would be %DOMINATRIX%/widgets)
  2. Each Widget should be in its own folder with the Widget Name (widgets/window_frame, widgets/minimap)
  3. Each Widget should have at minimum a markup.lua file. Loadable files include markup.lua, styles.lua, and scripts.lua.
  4. Widgets can be loaded into the DOM via markup or scripts and will be rendered into regular elements, retaining no "special" data indicating they are from a Widget.
  5. setting the ID of a Widget Element will set the id of the first element in the Widget.
  6. A Widget should have a single container such as a block or inline element with its contents fully encapsulated within.
-- main.lua
local dom = require "libs.DOMinatrix"
local gui = dom.new()
gui:add_widget_directory("assets/widgets/")
gui:include_markup("assets/gui/game_screen.lua")
-- game_screen.lua
return {
    { "window_frame", id="character_window" },
}
-- window_frame/markup.lua
return {
    { "inline", class="window_frame",
        { "text", class="window_frame_title" },
        { "button", class="window_frame_collapse" },
        { "button", class="window_frame_close" },
        { "block", class="window_frame_content" },
    }
}

Border Radius

Got this mostly working thats to @positive07 but this needs to be scaled down so the outside of the polygon is on the border edge, not the inside!

    -- https://gist.github.com/gvx/9072860
    local function get_stencil_clip(x, y, w, h, precision, corners)
        local polygon = {}

        -- true if on x/y, false if on w/h; TL, TR, BR, BL
        local xs = { true, false, false, true  }
        local ys = { true, true,  false, false }

        for i, radius in ipairs(corners) do
            if radius == 0 then
                table.insert(polygon, xs[i] and x or x+w)
                table.insert(polygon, ys[i] and y or y+h)
            else
                for j = 0, precision do
                    local angle = (j / precision + (i - 3)) * math.pi / 2
                    table.insert(polygon, (xs[i] and x or x+w) + radius * math.cos(angle))
                    table.insert(polygon, (ys[i] and y or y+h) + radius * math.sin(angle))
                end
            end
        end

        return polygon
    end

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.