Monday, December 30, 2013

New Year, New Goals

For some time, I have been somewhat undecided on the direction to take Mana as a product. My reason for creating it in the first place was that I want to use it for my own projects. However, it did occur to me that others might find it useful and that I could turn that assessment into a small business. The fact is I'd really get a kick out of seeing what people would do with it!

Hint: It's not just for games!

I spend a reasonable amount of time scouring the web and making mental notes on other products and what they offer. When this project began, I wrote a post about Adobe Air and neglected to mention Unity3D, which has clearly taken off and is now one of the go to tools in the game industry. There is no question that I have kept its popularity in mind when considering my business strategy. To a certain extent, I've been withholding Mana as a product until it matches its competition.

I believe the time has come for a small change in direction.

Mana is currently a Windows-only product, having been developed entirely on my aging XP computer and tested on my 8.1 laptop. OS X and Linux versions should be fairly easy ports thanks to BlitzMax, but currently I lack the necessary hardware.

Oh, and fear not, the XP machine will soon be replaced. My girlfriend assures me it is garbage, anyway!

The future is mobile and it would be silly to ignore that enormous market. It has always been my intention to see Mana used as a tool for education. To that end, the more devices that Mana can reach, the better.

That's where WebGL comes in.

Tuesday, November 12, 2013

Busy, Busy

The ThinkMartian web site is fleshed out and much prettier. With over a thousand Lua functions needing descriptions, I decided to spend some time working on a faster way to update the content. I needed a central repository for object data, since it will be used to construct blog posts, Lua glue code, and soon the offline help system.

Since I added MySQL database features a couple of weeks ago, I considered using them to store object help data. But Mana's help system cannot require a database be set up, so - it's XML instead!

I spent a day looking into the possibility of adding the Chromium Embedded Framework. Being able to include web page rendering directly in the Mana engine would open up some exciting possibilities. However, it proved to be a bit more challenging than I'd hoped and I was forced to abandon the effort for the time being.

Friday, October 18, 2013

Target Misplaced

There's a pretty funny opening scene in an episode of "Malcolm In The Middle" that involves Hal and the simple task of changing a light bulb. While getting the bulb off of a shelf, he discovers the shelf is loose. When he gets a screwdriver to fix the shelf, the drawer the tool is in squeaks. When he gets the WD-40 to silence the squeak - well, you get the idea!

My plan two months ago was to have an alpha version of Mana available online in very basic form. I figured it wouldn't be difficult to get a version up that allowed importing content for viewing purposes and over time, I'd trickle out the rest of the features. It turned out that even that simple goal uncovered a number of other things needing to be done.

For one thing, I needed a proper web site. As much as I'd love to hire out that work, I am at present a company of one with a budget of zero. I'm familiar with html and css, but I've never set up anything more complicated that requires php. So, I did what many have done before and turned to the internet for a solution. I wanted a blog site that I could grow into the face of my business. After some research, several false starts, and yet more hair-pulling, I have the framework set up for ThinkMartian.com - that's my brand, please wear it out! The site is not very pretty, but at least I have a place to start uploading Mana documentation.

Another thing I needed was a proper exporter. I use 3d Studio Max and have some scripts that export to the xml format Mana loads. However, the scripts were lacking an interface and I have since written one (maybe 90% complete). Even so, I didn't want to limit even my initial offering to people with 3dsMax, so I decided to spend some time hooking up the AssImp library. Its purpose is to import some thirty-odd common model formats. In the process of doing that, I realized Mana would need to load more image formats (e.g. DXTC) and that led to hooking up the FreeImage library. Yes, I do sometimes wonder if I'm participating in a (nerdy) sitcom.

But then, don't we all?

Thursday, September 5, 2013

Target Acquired

About two and a half weeks ago, I set a six-week goal for having my first "alpha" product functional. Each week would have its own set of goals coinciding with the premiers of the last six episodes of my current favorite television show, Breaking Bad. As of now, I'm quite behind schedule.

In part, the reason for my lateness (this time) is because I felt the need to finalize my decision about which physics engine to use. I've had Newton Game Dynamics hooked up for some time, but it's not being supported much these days. Its capabilities are limited to rigid objects - no soft bodies, cloth simulation, or built-in rope physics. Bullet, on the other hand, has all of those things and more and is getting updated frequently. I knew I'd eventually want to switch. Yet it was a complete unknown to me as to how to get Bullet, a C++ static library, working with BlitzMax. My plan was to put it off until it was absolutely necessary and probably to hire someone to do it (if possible).

However, I really wanted some basic rope physics in my demo. When I looked into using Newton for that, the official site was down. Leave it to fate to show me a new path! I took it as a sign that I should look into Bullet further, and I can now happily say that I'm glad I did. After a bit of head scratching and hair pulling, Mana now uses Bullet for its physics. The implementation still needs some work, but rigid objects, constraints, soft bodies and rope physics are all functioning!

As much fun as it would be to keep playing with Bullet for the next month and implement ragdoll and vehicles (vroom, vroom) and cloth physics, my original six-week target is calling again.

Monday, May 13, 2013

Lifus Interuptus

I had intended to update more often, but an unfortunate act of clumsiness rendered my right hand more or less useless for the past month. In addition, I went on a short trip to Illinois and made some repairs to the condo I was in the process of selling. All of this non-Mana-related stuff has slowed the momentum I had in March.

Never fear, work on Mana continues! At the moment, I am making decisions regarding the interface. I am finding it to be much more work than I anticipated simply because there are so many possible approaches to design and functionality. Since I expect Mana to be ported to many different platforms eventually, I believe it is best to consider those targets when designing the interface. In other words, when Mana is running on Android or iOS, I would prefer that the interface still function in a predictable and consistent way without sacrificing the features we have all come to expect on the PC (and Linux and MacOS) and without having to make many platform-specific exceptions.

To that end, mouse hovers will be limited mostly to highlighting widgets and perhaps providing tool tags for desktops only. Right-click menus will be functional on desktops, but they will also have visible triggers in order to serve touch screens. Of course, it will be possible to use Mana to create virtually any kind of interface, but I think it is important to keep Mana itself reasonably device independent.

Tuesday, March 26, 2013

Marching Orders

In my last post, I compared objects in the Mana internal directory structure to the files residing in folders on your computer. Taking that a step further, Mana objects have something else in common with files. They can be put into one of two general categories - data or executable (functional).

Most files on your computer are simply data that is read in by applications. Similarly, most objects in Mana are merely containers. Models, widgets, lights, cameras, and so forth are all basically data associated with names. But applications are driven by functions that carry out instructions on those objects.

In Mana, functions are objects like any other and, in a sense, most objects act like functions.

Confused? I don't blame you!

Mana operates something like a set of dominoes. One object of your choosing is the start of a chain of events that unfolds the purpose of your application. Every object has a set of things in common and chief among those is an Update method.

That is important! So I shall reiterate!

Every object has an Update method and all objects are linked in a hierarchy. Updating an object cascades down through all of its children and their children and so on. Like dominoes! If you want your application to run in a loop, use a looping function at the top of your chain.

Now, back to functions! Here is a simple, and rather silly, one written in Lua.

function MakeMultipleWindows( n )
    for i = 1, n, 1 do
      mkWindow( "Window" .. i, 0, i * 110, 200, 100 )
    end
end

It expects one integer parameter and makes that many windows. Functions written like this are available only in Lua and there's nothing wrong with that. Entire applications can be written this way and there's nothing stopping anyone from sharing scripts!

However, if a function is to be executed as part of a chain, it is best registered as an object. That declaration looks something like this.

MANA.RegisterFunction(
    function MakeMultipleWindows( n )
      for i = 1, n, 1 do
        mkWindow( "Window" .. i, 0, i * 110, 200, 100 )
      end
    end,
    "MyFunctions/MakeMultipleWindows",
    {MANA.META.INT},
    {}
)

The MakeMultipleWindows function is registered as a function object that can be cloned and attached to other objects and have children of its own. I'll leave the breakdown of the syntax for later. One other benefit of registering functions is that they are packaged as part of the module and that makes distribution simpler.

As you may have guessed, linking functions together in combinations can have powerful results!

Wednesday, March 20, 2013

Understanding Parents

All objects in Mana belong to a system reminiscent of a family tree, or if you prefer, a system of folders (directories) and files. The root object is always a module and can be used in combination with other modules in a variety of applications. Also, modules can be distributed on their own so that they may be shared and used in numerous projects.

Objects that are in directories or that are directly linked to other objects can be found using a path name.

    //Prototypes/Widget:Window

The above statement refers to the Window prototype object in the Prototypes/Widget directory. The two slashes at the beginning indicate that it is found in the main tree. The colon represents the end of the directory path and the start of the object path, but the parser is forgiving and will accept a slash. The following is also valid.

    //Prototypes/Widget/Window

Widgets are often made up of sub-widgets. Objects that are children of other objects can also be accessed using path names.

    MANA.Find("//Prototypes/Widget:ScrollPanel/ScrollArea")

The code above returns the scroll area of the prototype scroll panel. Mana uses a prototype/clone system for creating and extending objects. Prototypes are objects with which the end user does not directly interact, but are strictly used to define other objects. When a prototype is cloned, its properties (fields and methods) and all of its children are cloned and become part of the new object.

Here is that window definition from my last post, with some additions.

MANA.Start()
    MANA.Clone( "//Prototypes/Widget/Window", "MyWindow", -1, "//MyGui" )
    MANA.THIS:SetPosition( 50, 50 )
    MANA.THIS:SetSize( 300, 200 )
    MANA.Clone( "//Prototypes/Widget/Button", "OkButton", -1, "..MyWindow/WindowPanel" )
    MANA.THIS:SetAlignment( -1, 2, -2, -1, 1, -2 )
    MANA.THIS:SetSize( 80, 30 )
MANA.Finish()

The second line (after Start) creates a clone of the window prototype, names it "MyWindow", and attaches it to the end of the list of child objects for another object in the tree called "MyGui." Any object created using Init, Clone, or ReadXml between the Start and Finish statements is available on an initialization stack. It can be accessed immediately using the THIS field of the MANA table or using Find with two dots in front of its name.

    MANA.THIS:SetPosition( 50, 50 )

The code above sets the position of the last created object (MyWindow) to 50, 50.

    MANA.Clone( "//Prototypes/Widget/Button", "OkButton", -1, "..MyWindow/WindowPanel" )

This line creates a clone of the button prototype, names it "OkButton", and attaches it to "MyWindow." The two dots refer to an object previously created on the stack.

NOTE: The WindowPanel sub-object is referenced because windows are made of other components and attaching directly to the window would overdraw them. Your button may draw on top of the frame or title bar and that simply won't do!

Here is an alternative.

    MANA.Clone( "//Prototypes/Widget/Button", "OkButton", -1, ">>MyWindow" )

In this variant, the two dots are replaced with two right angle brackets and WindowPanel is omitted. Some objects have an attachment facility, or a set of instructions that regulate how other objects get attached. In this case, the window is being instructed to process the button and attach it to the correct location automatically.

Friday, March 15, 2013

I Love Lua

Warning: Those technical posts I promised two years ago are finally happening! :-)

Has it been five months already!?

It is time to announce that my project has an official name - Mana. The word originated in the Pacific islands and refers to an "impersonal force" that resides in all things. Gamers, especially RPG gamers, should recognize it instantly. It is often used in games to quantify magic or life force in the form of points.

It is also time to express my love for the Lua scripting language. My first stab at getting Mana and Lua working together was actually quite some time ago. It went so well that I ended up abandoning my own scripting language and embracing Lua for its popularity, speed, and ease of use. The integration is about ninety percent - almost anything can be done externally in script!

Using Lua, there are essentially three ways to create objects. There is a low-level interface, common to all objects and designed to provide consistency for all classes. On top of that, there is the MANA stack, which uses the same low-level methodology, but keeps track of a few things to make the process simpler. Then, there are the more convenient “mk” functions that are single line object initialization functions.

Most of the time, the “mk” functions will probably be the most commonly used.

tex = mkTexture( "MyTexture", 256, 256 )
--Returns 256 x 256 blank texture.

v3 = mkVec3( 0, 1, 0 )
--Returns an ‘up’ vector.

win = mkWindow( "MyWindow", 50, 50, 300, 200 )
--Returns a window widget.

They initialize objects based on whatever the currently active template calls for. But more on those later. For now, I’ll write a bit about the MANA stack. This is a low-level interface that provides a typical “start new object, modify object attributes, then finish object” methodology.

There are three standard functions for creating an object - ANY object. This applies to widgets, models, textures, materials, and their components - EVERY object that is in Mana. Those three functions are Init, Clone, and ReadXml (ReadBin may be added later).

    Init - creates a new superclass object from scratch.
    Clone - creates one from an existing object.
    ReadXml - reads the data for an object from an xml file and the return value may be a new object or a clone, depending on the file.

Each of the creation functions takes four parameters of a similar nature.

    Init( superclass, class, index, parent )

Superclass and class are strings describing the new object. Superclass refers to all of the base type objects available in Mana (Widget, for example). Class is used to define a new class or, for objects that can’t be reclassified, a name.

    Clone( path, name, index, parent )

Path is the string path to the object to be cloned, and name is the new object name.

    ReadXml( filename, path, index, parent )

Filename is, of course, the file to be read, and path is the path to the node that contains the data.

All three functions use index and parent. Parent is the string path to the object that the new object will be associated. Index is used when a new object is being created to replace another. However, the default is -1, meaning “append new object to the end.”

The following code does the same thing as the mkTexture and mkWindow statements above, only much more verbose!

MANA.Start()
    MANA.Init( "Texture", "MyTexture", -1, "++Textures" )
    MANA.THIS:SetSize( 256, 256 )
MANA.Finish()
MANA.Start()
    MANA.Clone( "//Prototypes/Widget/Window", "MyWindow", -1, "//MyGui" )
    MANA.THIS:SetPosition( 50, 50 )
    MANA.THIS:SetSize( 300, 200 )
MANA.Finish()

But why would anyone want to write all that code to do something so basic?

Why, indeed!! It is really just a common way of creating all objects of all types. Start creating an object with its default values, then change the parameters, then finish with an object that is available to be cloned and used for all sorts of things. If I had omitted the SetSize line from the texture code, for example, it would still return a 256 x 256 because those happen to be the default values.

But wait! What does that parent value mean, exactly?

All objects in Mana are linked together in a hierarchical structure in a way that resembles files and folders on your hard drive. In my next post, I’ll cover that in more detail.