I made a UI library called Unit.

Hi! I’m new here. I’ve had Codea for a few years, and I made my own library for a UI a while back. I still consider myself to be a bit of an amateur, so I want to share this code for feedback. What did I do right? What did I do wrong? Go ahead and tell me!

You can see the code (as well as other details about the project) here (https://github.com/calm-dolphin/Unit-UI).

There is more information in the repo, but basically it all centers around the Unit.Panel class, which has ‘hot-swappable’ functions to handle touch events and the screen size changing. I don’t know if it will really be useful to anyone at this point, especially considering the lack of switches/sliders/asset-based UI elements… but I thought I should share anyway! Should continue work on it?

Edit: Added a file on the post for easier access
Edit 2: Added an example project for better demonstration. It is also located here: https://github.com/calm-dolphin/Adventures-With-Billy

*** Don’t forget to add Unit as a dependency for the demo.

Hi @calm_dolphin, I suggest you attach the project as a .zip file to your post, that’s the easiest way for people to check it out.

I went and looked at your Main.lua file and at first glance I think it’s pretty nice work—it’s like a declarative UI scripting library—though I’m not a pro at all either.

That said, the screenshots look kind of basic, especially next to things like SODA—and I agree, SODA has an intimidating learning curve—but I wonder if it would be theoretically possible to use your API structure and hook it up to SODA under the hood…

@calm_dolphin Thanks for posting your work. I downloaded your zip file, much easier than going to GitHub. Your basic demo displays some things, but probably not enough to show the full potential of what your code can do. Looking through your instructions, I wasn’t able to get it to do anything. I normally don’t run any code where I have to spend a lot of time trying to figure out what to do to get it running. My suggestion is to write a small example program and post it here that uses your library to give people like me something that runs without having to look thru the code on how to use it. It doesn’t have to be anything super, just enough to show off your library. You’ll probably get a lot more users trying it. I always try to post a running example of my code, so anyone who wants to look at it has nothing to do but execute it.

You probably put a lot of work into this, so the easier it is to see what you’ve done, the more responses you’ll get.

I don’t like to use other people’s library because I don’t want to load a lot of code that doesn’t get used just to use one or two things. I also don’t want to depend on them to update their code when something breaks. Don’t worry about being compared to SODA. That was done by an experienced programmer and I’m sure a lot of time and effort was put into it.

Hope to see more posts from you on the forum.

@UberGoober Thank you for taking a look! It sounds like you think the API is easy to use, which is good to hear. I know that I could get theoretically this system to be as functional as Soda if I put enough work in. Whether I could use an API like this to use Soda is in interesting idea I hadn’t thought of before. I suppose it is possible, though it sounds like it would be inefficient.

@dave1707 Thank you for taking a look, too! I actually already have a project that uses this library, which I somehow failed to realize would be useful for everyone here. I’ll link it here. It’s also on Github again: https://github.com/calm-dolphin/Adventures-With-Billy

The project is a bit messy, especially in the way it handles the assets (that I made by the way), but it should demonstrate Unit’s functionality better. Thank you for the suggestion!

*** Don’t forget to add Unit as a dependency when using the below demo.

@calm_dolphin Thanks for the demo. It’s a lot easier to look at your work. I added the comment in your above write up to add Unit as a dependency. I got errors in the code until I remembered the dependency.

@calm_dolphin

Like the name!

Can I ask what your goal is?

Are you intending to make a UI library for other people to use?

@UberGoober
To be honest, my main goal is education. I decided to make Unit anticipating that it would be a fun, educational experience, which it was. I’m sharing it mainly to get out of the ‘solo developer bubble’ and get some proper feedback. But I’m also interested in the idea of continuing work in the open if it seems like it could be useful to people. I don’t know whether the Codea community is interested in a new UI library at all— and if they are interested, I don’t know whether my project has the potential to fit the bill.

Basically, if the Codea community is fine with the UI stuff they’ve got, I’ll happily take some project feedback and go on my merry way. But if the Codea community is really interested and sees potential, I’ll consider updating it and sharing news in the future. I want to see what other people think before deciding what I want to do with Unit.

@calm_dolphin I just had a play with your example and while I haven’t had a look through your UI library design yet, I just wanted to say that the indoor/outdoor transition is one of the coolest I’ve seen! I love the way it zooms into the building and switches to the interior

@Simeon Thank you! I spent a good bit of time on that game (though it is more of an engine than a game at this point). It was great fun teaching myself some basics about 2D graphics. The “zooming” is simply tweening the World.pointSize variable (with tween.easing.cubicInOut), which changes the sizes of each ‘block.’ Of course, it is probably the crunchy door-closing sound effect that really sells it :smiley:

I don’t want to discourage you, but if your goal is to have other people use it, I feel like I should tell you what I’ve observed.

Over the years, a lot of different people have posted UI code here for others to use, yet it seems like, no matter how good it is, people on the forums just don’t use other people’s UI.

It’s probably for the reasons @Bri_G guessed at in a post here,

The reasons I don’t use other people’s code in mine.

1.) I don’t want to have a lot of code just to use one thing.
2.) I don’t want to wait on the other person to fix code when something changes.
3.) I don’t want to spend a lot of time trying to figure out how to use it.
4.) There are probably other reasons if I want to spend more time thinking about it.

@dave1707 in your particular case, if you don’t mind me praising your skills a little, I think it might also be a factor that you can probably do just about anything you want by yourself, and likely in less time than it would take to import someone else’s project and enable it as a dependency.

@UberGoober Thanks. But the way I got like that was because I did my own coding. I might have looked at someone else’s code to see how something I didn’t know about was done. But basically I would continuously write small projects that did specific things and then constantly modify them until I fully understood what was happening. That’s how I can pop little examples of code that someone might ask about in a short time with only doing a little modification.

You both make very good points. I think I can understand where other Codea users are coming from, considering that I decided to make my own UI system rather than use a pre-existing one.

I’ve already made it clear that my main goal is education rather than making something for other people to use, so I’m satisfied. I’ll update Unit even if no one but me uses it, because it is still a fun challenge for me (though I can’t guarantee that it will continue to be interesting to me forever). And it is nice to know that people might look at my code and, even if they don’t use it as a dependency, might be inspired by it. I can definitely say that I’ve been inspired by the Codea example projects, other UI systems such as Soda, and other unrelated projects that make me reconsider what is possible with Codea.

It would be ideal to have a strong, vibrant community around Codea projects, but if we are being honest, programmers are traditionally lone wolves and usually only work together when the project is really important. And I don’t think Codea is a primary tool for important iOS projects. Codea is great fun, and it is very educational, but it just isn’t the kind of thing that would make investing time learning a UI library really worth it.

But it should at least be the kind of thing that you can post on a little forum and get some feedback on, right? I think Codea fits that niche well. I understand that my project is rather large, and I greatly appreciate any effort you put into looking at my project. And if you decide to use it or make something inspired by it, that’s even better. I think it’s important to remember that none of us owe each other anything— everything that is given is given freely. So I’ll take all that I can get, and I’ll l share when I think I can help and it isn’t too much work.

@calm_dolphin I think you’re understanding what’s really happening in this forum. It’s mostly for fun, learning, sharing, and helping others. I’ve been here for 9 years and it’s still fun for me. There’s still things I don’t know and with all the examples that keep showing up, that makes it easy to learn.

@calm_dolphin glad to hear it, I think you won’t be disappointed then.

So I have comments to make on the code itself, but I think their relevance also depends on your priorities.

For me, if I’m going to use someone else’s code, my #1 priority is that it’s easy to learn, and if that’s a priority for you too, I think you’d get a big return from putting some of your attention on first impressions, and on doing everything you can to make the best first impression you can.

So I think what I’m getting at specifically is called Emergent Complexity. Have the thing look incredibly simple up front and then lead the user slowly into understanding the other complex abilities it has to offer.

So specifically specifically I’d work on getting the first code a user sees to be so simple that they immediately feel like they know how to use it. This means that instead of having the first code in your project show off the full scope of all the cool things your API can do, it possibly would be better to actually show the least it can do. It might be best to show off how well it works when you don’t try to do anything fancy at all.

So specifically specifically specifically, I’m basically saying I’d recommend making way more use of default values.

Another thing with making complex code for others to use, unless you’ll be around forever to support any problems that come up with new versions of Codea or iOS, anyone using you code could have unusable code in the future. They’ll be sending you requests for a fix which you occasionally see here. But then that’s user beware.

I think I want to prioritize making my code simple to use. The idea is that you define a Unit.screen object for every collection of panel-like objects, and the parent-child relationships between UI elements can be represented naturally, using nested tables. So, to the user, every panel (screens and buttons are specialized panels) has two tables: a table of attributes, such as color, button function, etc, and a table of children. And then each child has their own table of attributes and children.

I definitely want to beef up the default values, but I also want to make inheritance between parents and children modular. Right now, inheritance is only in place for size— i.e., the size of the child panel depends on the size of the parent panel. I’m not sure whether children should, by default, inherit all of their undefined attributes, or if they should only inherit ‘basic’ values like colors. A fully modular inheritance system would make this less of an issue, but to make the system as easy to use as possible, I also need to know what functionality is the most intuitive. Sometimes that is difficult to see. For panel size, it was relatively straightforward— all panels’ sizes are defined as percentages of their parent panels, by default. But what does this mean for color or shape or even functionality? I’m thinking that maybe color and shape should be inherited (when they aren’t explicitly defined) instead of getting top-level default values, but if I make too many inheritance rules, it can seem arbitrary.

Right now, I’ll focus on documentation and immediate ease-of-use. I’m slowly updating the wiki on Github, though I’m not sure that is the most effective documentation. I’ve also thought about including a tutorial (or at least some kind of onboarding) within the Unit project, though I’m not sure how to go about that. The lazy way is to print a long string in Unit.setup(), and that could suffice if there is sufficiently accessible information in other places.

An easy first step for me would probably be making it possible to write myScreen = Unit.screen() in the setup function without failing an assertion. I can see that as an easy first step in a tutorial for Unit. Then I could probably make Unit’s version of a “Hello World” program, which could add a text panel in the middle of the screen.

Right now, I consider Unit to be in an ‘alpha’ state, meaning that it is early in development and much of its API is still subject to change. Eventually, the API should stabilize, and once I have a nice, stable codebase with all the core features, I’ll work more on features. It’s an interesting journey, and I’m excited to see where it goes.

You’ve obviously put a lot of thought into this, so I hope it’s not super irritating for me to attempt to suggest something.

I think simplicity is an eminently noble goal, and as I’m sure you know, the devil of it is that simplicity is anything but easy.

I think it might yield great rewards to, at this moment In particular, just spend a little more time pondering what exactly you mean by “simple.”

I’ve been working on a major update for Unit for over a week now, and the changes just keep coming. It seems like whenever I’m almost done, there’s another thing to add…

Here’s a changelog so far:

  • Standardized “frameManager” system so that it makes more sense
  • Completely revamped touch input system, making it easier to define various touch input functions and increasing the power of touch functionality with flags like “reenteredFlag” and “exitFlag”
  • Deleted a lot of unused/unfinished code
  • Standardized default values in a “Unit.default” table.
  • Fixed bug where updating touches interfered with “hold” touch events
  • Removed many unnecessary assertions, making things easier to use and allowing default values to shine
  • Standardized class names to use UpperCamelCase. Also updated some names. What was previously Unit.button is now Unit.TextButton, which inherits from both Unit.TextPanel and Unit.Button, which in turn inherit Unit.Panel.
  • Updated handling of different draw modes. Unit now uses only CENTER drawing mode internally. When other draw modes are used, the input is internally converted to CENTER, which greatly simplifies the Unit.Panel:hit() method among other things.
  • Updated Unit.options and Unit.metrics tables so that they make more sense.
  • Introduced Unit.Screen:setCurrentScreen() method that makes switching screens a bit easier.
  • Rebuilt “style” system from the ground up, making it easier to swap out all the drawing parameters from Unit.Panel-like objects. The “highlight” system for buttons now uses the new Unit.Panel:changeStyle(style) method.
  • Some other stuff that I’ve not bothered to elaborate on here

So… my question now is, should I wait until I feel like the update is “done,” or should I work towards a stable release? Should I set explicit goals to accomplish so I don’t just work forever? Or should I just work as much as I feel like? Maybe that doesn’t matter a lot in this situation, but I thought I should at least tell people what I’ve been doing so that the project doesn’t seem abandoned.

I’ve also considered using a version control system. Are any of you familiar with version control? Maybe that’s a topic for another thread, though.