Wednesday, September 8, 2010

Beans Should Be Deprecated - The Future of Object Architecture With Properties (Part 2 of 2)

In part 1 we discussed the basics of properties in Sgine, how to listen for events, what a delegate property is, how to filter properties, transactions with properties, and animation. In this part we will conclude our tutorial of properties in Sgine with a discussion of paths in properties, binding support, property containers, dependent property, and advanced property.

Path-based Properties


In Sgine there is a unique path system. However, this is not a typical path system because it represents object paths, not filesystem paths. In the org.sgine.path package there is a class called OPath (object path) that can represent the hierarchical path to an object. So, for example, take the following code:
import org.sgine.property.MutableProperty

class Person {
    val addresses = new MutableProperty[Addresses]
}

class Addresses {
    val billing = new MutableProperty[Address]
    val shipping = new MutableProperty[Address]
}

class Address {
    val line1 = new MutableProperty[String]
}

Now, presume I have a reference to an instance of a person object, and I want to listen for any changes to address line1 on the shipping address. This is difficult as "addresses" is mutable, "shipping" is mutable, and "line1" is mutable. So, if I do the following:
person.addresses().shipping().line1.listeners += shippingLine1Changed _
I may get a NullPointerException because something isn't initialized, or I may connect up, but when any one of the mutable chains in-between break I'm now referencing the wrong data. This is where OPath comes in. I can pass a root reference and a path as a String and it can resolve the underlying object and return Option[T]. So for example, if I want to resolve the value as above with an OPath I can invoke:
val o = OPath.resolve[String](person, "addresses().shipping().line1()")
The value of "o" will be Some[String] representing value of line1 or None if any point in the hierarchy is not able to be resolved.

Now, back to properties. The PathProperty works with OPath instances (calling resolve like above simply resolves the value, but an OPath instance is a long-term reference to that path that receives events when anything changes). So if we wanted to create a property and know when the value of line1 in the shipping address has changed we could do the following:
val shippingLine1 = new PathProperty[String](OPath(person, "addresses().shipping().line1()"))
shippingLine1.listeners += shippingLine1Changed _

Your listener would look like this:
private def shippingLine1Changed(evt: PropertyChangeEvent[String]) = {
    ... shipping line1 has changed ...
}

Binding


I mentioned earlier that events were probably the most used feature in properties, but binding is likely a close second. The premise of binding is fairly simple. You have two values and you want one or both to replicate the value of the other. Newer frameworks like Flex and JavaFX make heavy use of binding and do a decent job of it. However, there's a lot that Sgine provides that they have no ability to do. Alas, I'm getting ahead of myself. Let's first take a look at a simple example. Consider the standard UI usage of binding. We have a CRUD app that manages people, so we have a text field that when updated needs to modify the name of the specific person we are working with. We must first modify our Person class to support binding:
import org.sgine.property.BindingProperty
import org.sgine.property.MutableProperty

class Person {
    val name = new MutableProperty[String] with BindingProperty[String]
}
Now, presuming we have a text field with signature like the following:
class TextField {
    val text = new MutableProperty[String] with BindingProperty[String]
}
We can simply take our Person's name and bind it to the text field's text property:
person.name bind nameField.text
Now any changes that occur to the nameField will automatically be applied back to person.name. This is the simple case and pretty much the extent to which most binding systems function. However, as I stated before, in Sgine binding support goes well beyond that.

The first problem you often run into with standard binding functionality is that you can only bind the same type of properties together. For example, in the previous case we were binding the name of a person to the text value of a text field. These both were String representations, but what if we wanted to do something like have an "age" property that is bound to a "birthday" property? We have an Int that wants to link up to a Calendar? This brings us to translation bindings.

Translation Binding


Translation binding is very similar to standard binding except there is a translation step that must occur to get the value ready for use in the target.

Lets look at the age / birthday example:
import java.util.Calendar

import org.sgine.property.BindingProperty
import org.sgine.property.MutableProperty

class Person {
    val age = new MutableProperty[Int] with BindingProperty[Int]
    val birthday = new MutableProperty[Calendar] with BindingProperty[Calendar]

    age bind(birthday, determineAge)

    private def determineAge(c: Calendar) = {
     if (c != null) {
         val now = Calendar.getInstance
         val age = now.get(Calendar.YEAR) - c.get(Calendar.YEAR)
         now.set(Calendar.YEAR, c.get(Calendar.YEAR))
         if (now before c) {
             age - 1
         } else {
             age
         }
     } else {
      -1
     }
    }
}
We simply bind birthday to age, but at the same time provide a function to convert from a Calendar to an Int. Now every time birthday changes, age gets updated.

Path-based Binding


As we've already discussed, OPath in Sgine represents an object-path to a value within a hierarchical structure. We've already seen it used to resolve values directly and with PathProperty. Now we're going to look at one of the most powerful uses of OPath, and that's for binding. Often you want to bind to a hierarchical value that may or may not exist at time of instantiation. The solution to this generally is to add a listener, to wait until it has been defined, and then add the binding. Later though, the reference structure may change or be set back to null and you find yourself with a binding to something that is no longer being used. With path-based bindings you can bind to a hierarchical structure and no longer concern yourself with the details of parts changing in-between. Every time the path changes the binding will be updated.

For example:
import org.sgine.path.OPath

import org.sgine.property.BindingProperty
import org.sgine.property.MutableProperty

class Person {
    val lastName = new MutableProperty[String] with BindingProperty[String]
    val spouse = new MutableProperty[Person] with BindingProperty[Person]
}
Now, consider that this person has stated they want their lastName to be bound to that of their spouse's. We could do this:
person.lastName bind person.spouse().lastName
But it's possible they are not yet married, and it's also possible that the spouse might change. If we do a path-based binding instead, no matter if they are married now or change spouses in the future, the binding will remain pointing to their spouse's lastName:
person.lastName bindPath OPath(person, "spouse().lastName()")
Though a little hard to grasp at first, the benefits of such functionality significantly reduce the amount of handling that must be added in order to deal with multi-level mutability.

Property Container


Properties by themselves are quite useful little beasts, but add PropertyContainer to this mix and the benefits multiply. One of the troubles you have with the standard bean scenario is introspecting the contents of that bean in order to find out what values it contains in order to make use of it. Inevitably Reflection is used to determine the fields or methods that make up that bean. PropertyContainer eliminates the need for manual Reflection.

The ability to know what properties exist for a specific instance can be very useful. Rather than pushing back the necessity to use Reflection onto the developer, PropertyContainer dynamically introspects the instance in order to determine what properties are available and by what name they can be referenced. For example:
import org.sgine.property.MutableProperty
import org.sgine.property.container.PropertyContainer

class Person extends PropertyContainer {
    val name = new MutableProperty[String]
}
Now, I can iterate over all the properties of my "person" with:
for (prop <- person.properties) {
    ...
}
I can also do a lookup of a property by name:
val name = person("name")
Another very useful feature to PropertyContainers is that they are also Listenable instances, so they can receive events. This gives you the ability to listen for events on the container and receive events for the children. See the following example:
import org.sgine.property.ListenableProperty
import org.sgine.property.MutableProperty
import org.sgine.property.container.PropertyContainer

class Person extends PropertyContainer {
    val name = new MutableProperty[String] with ListenableProperty[String] {
        override val parent = Person.this
    }
}
It's important to notice here the only revision that needed take place is that "name" provide a reference to the Person instance via the "parent" property. This is used to propagate the event up. This can allow a complete hierarchical structure to propagate all the way up to the top. Now we can add a listener with the following:
import org.sgine.event.EventHandler
import org.sgine.event.Recursion

import org.sgine.property.event.PropertyChangeEvent

val person = new Person()
person.listeners += EventHandler(propertyChanged, recursion = Recursion.Children)

private def propertyChanged(evt: PropertyChangeEvent[_]) = {
    ... property changed ...
}
The above example will be invoked if any child throws a PropertyChangeEvent. Finally, beyond the static PropertyContainer we also may need to add and remove properties dynamically. This is where MutablePropertyContainer comes in. MutablePropertyContainer, as the name suggests, allows dynamically adding and removing properties on the fly rather than relying on Reflection in order to determine names and references.

Dependent Properties

DependentProperty allows for the default value to point to another property instead of the initial value of that property. For example:
import org.sgine.property.DependentProperty
import org.sgine.property.MutableProperty

class Person {
    val name = new MutableProperty[String] with DependentProperty[String] {
        val dependency = Person.defaultName
    }
}

object Person {
    val defaultName = new MutableProperty[String]("Anonymous")
}
The value of person.name is defaulted to point to whatever the value of Person.defaultName is. Even if the value of "defaultName" should change after initialization it will continue to point to it until the value of the "name" property itself has been changed. This is particularly useful for stylization as it allows default styles to exist but without removing the ability to explicitly override.

AdvancedProperty

In the examples above there is a lot of mixing of traits to achieve the desired functionality, but in most cases there is no reason not to make all of this functionality available. For simplification the AdvancedProperty combines all the standard functionality that might be desired in a property without sacrificing performance. The traits that AdvancedProperty mixes in by default are:
  • MutableProperty
  • DepedentProperty
  • ListenableProperty
  • NamedProperty
  • BindingProperty
  • AnimatingProperty
  • EventDelegationProperty
  • CombiningProperty
Simply instantiating AdvancedProperty is much easier than concerning yourself with every possibly trait that might be needed on a given property and in general there's nothing lost by doing so. AdvancedProperty does not contain all the available traits for properties, but additional traits can be mixed in as needed. To use AdvancedProperty is quite simple:
import org.sgine.property.AdvancedProperty

class Person {
    val name = new AdvancedProperty[String]("")
}
This gives you all the functionality you are likely to need in "name". If you are taking advantage of PropertyContainer you can use the following signature instead:
import org.sgine.property.AdvancedProperty
import org.sgine.property.container.PropertyContainer

class Person extends PropertyContainer {
    val name = new AdvancedProperty[String]("", this)
}

Conclusion

This has been a lengthy tutorial about the functionality that is provided in Sgine's Property system, but hopefully provides the foundation necessary for you to start taking advantage of Properties in your projects. The focus of Sgine is very much toward 3d engine development, but much of the foundation is geared toward general usage. To that end it is my desire that functionality such as the Property system may be leveraged in diverse systems that may have nothing to do with graphical programming at all. Though this was a lengthy examination of properties it did not go over every feature and trait available in Sgine. For additional information please refer to the ScalaDocs for Sgine.

Beans Should Be Deprecated - The Future of Object Architecture With Properties (Part 1 of 2)

In my previous post I discussed the case for Properties and the basics of how they work. In this post I will dive into the specific workings of Properties in Sgine and how to use the various features it provides.

This post is all about Properties in Sgine for use primarily with Scala. However, I know many people, for whatever reason, are still using Java. For those people I would like to point you to this post I made a year previous regarding Properties in Java and the implementation of Properties in the open-source project xjava.

Basics


In Sgine Property is a trait that extends Function0[T] (getter) and Function1[T, Property[T]] (setter). This basic foundation allows better compliance of use along with functional delegation. Here's a simple example class implementation of a Property:

import org.sgine.property.Property

import scala.reflect.Manifest

class SimpleProperty[T](protected implicit val manifest: Manifest[T]) extends Property[T] {
    private var _value: T = _

    def apply() = _value

    def apply(value: T): Property[T] = {
        _value = value

        this
    }
}

This is relatively straight-forward to the way properties were discussed in the previous article with one glaring difference. The use of Manifest is a very cool feature in Scala that Sgine takes extensive use of. If you're not familiar with Manifest I suggest reading more here. If you are familiar with erasure Generics in Java you'll know that Generic type information is not available at runtime, it is purely a compile-time feature to maintain static-typing. However, there are many cases where having that information at runtime is extremely useful and that's exactly what scala.reflect.Manifest gives you. Fortunately though, the only case in which this knowledge will be necessary is if you need to extend Properties, which will never be necessary for the majority of developers.

Now that we have our SimpleProperty class we want to use it:

class Person {
    val name = new SimpleProperty[String]()
}

val person = new Person()
person.name("John Doe")
val name = person.name()

Now that we understand how easy it is to create properties, lets put that knowledge aside for now. As I stated, you'll probably never need to do this, but hopefully this helps you understand how easy it is to do if you should desire to do so.

Moving on, Sgine already supplies all the functionality demonstrated in SimpleProperty in org.sgine.property.MutableProperty. This class is the base for most of the standard mutable Property functionality in Sgine.

The above example requires the creation of your own Property class, but you can use the built-in MutableProperty:

import org.sgine.property.MutableProperty

class Person {
    val name = new MutableProperty[String]()
}

val person = new Person()
person.name("John Doe")
val name = person.name()

Because setting name via apply:
person.name("John Doe")
Is not the most intuitive to realize it is setting the value of the Property, there are a couple additional convenience methods in Property that invoke the same functionality but may be more readable in code.

The first is ":=" so you can write:
person.name := "John Doe"
This is what I personally prefer when setting the value of a Property as it is quite clear that I am intentionally modifying the value of person.name.

Additionally you can use "value" for both getting and setting:
person.name.value = "John Doe"    // Setter
val name = person.name.value    // Getter

Usage aside, Properties are quite simple in concept and though every implementation has its own details you must understand, you hopefully have a good foundation to start with. In the next sections we will be building upon this foundation with specific functionality that Sgine provides to make Properties that much more powerful and effective.

Events


Events in properties are arguably the most useful feature in any properties framework and definitely the most requested feature to any properties system. Sgine provides a complete Event system that is general purpose apart from properties, but is utilized in the properties system to provide a simple, yet complete event system.

The relevant trait we'll use for event handling is ListenableProperty. Here's a sample of setup:
import org.sgine.property.ListenableProperty
import org.sgine.property.MutableProperty

class Person {
    val name = new MutableProperty[String] with ListenableProperty[String]
}

Notice we simply had to mix-in the ListenableProperty to our MutableProperty and now we've got event support in our "name" property.

Here's an example to listen for change of "name":
val person = new Person()
person.name.listeners += nameChanged _

Notice here that we simply reference the "listeners" instance of "name" and invoke "+=" to add our listener.

The definition of our listener "nameChanged":
private def nameChanged(evt: PropertyChangeEvent[String]) = {
    println("Name Changed!")
}

Like I stated previously, the event is extremely powerful and can do some really awesome things, but for the purposes of this tutorial we'll keep it to simply mentioning that we can reference as our "listener" any method/function that takes an Event and returns Unit. In the above code we are explicitly wanting to receive PropertyChangeEvents for Strings and the internal event system will filter all other events from getting to our listener method.

Now every time we change "name" an event will be thrown to "nameChanged".

Another tutorial needs to be written in the future to explain the features and functionality provided in the event system, but you now have the basic knowledge to listen for events in properties.

Delegate Properties


DelegateProperty is an alternative base property to MutableProperty. Instead of maintaining a value internally within the property itself, it delegates to outside functions for getting and setting values. This is most useful when dealing with existing code. Consider the following example:
import org.sgine.property.DelegateProperty

class Window {
    private val frame = new javax.swing.JFrame()

    val title = new DelegateProperty[String](frame.getTitle _, frame.setTitle _)
}
This example is a simple wrapper around Swing's JFrame, and though we could create a title property, listen to changes, and then apply them to the underlying JFrame it would be quite a bit of effort (and a lot more code) to do so. Instead, since all we want to do is replicate the functionality from JFrame's getTitle/setTitle methods we can just delegate to and from those methods. This allows us to utilize all the features of properties while relying on existing functions.

This can also be useful for more complex scenarios where determining the value requires some internal processing. You simply specify your getter to point to a private method/function that does the work and you're finished. The setter function is an optional parameter and if unspecified will throw an UnsupportedOperationException if invoked.

Filtering


FilteredProperty provides the ability to modify an incoming value before it gets applied to the property itself. See the following example usage:
import org.sgine.property.FilteredProperty
import org.sgine.property.MutableProperty

class Person {
    val name = new MutableProperty[String] with FilteredProperty[String] {
        val filter = (s: String) => if (s == null) "" else s
    }
}
This simple example converts nulls to a blank String. This allows you to work with "name" without ever being worried about its value being null.

Another usage of this would be to disallow specific values by throwing an Exception:
import org.sgine.property.FilteredProperty
import org.sgine.property.MutableProperty

class Person {
    val name = new MutableProperty[String] with FilteredProperty[String] {
        val filter = (s: String) => if (s == null) throw new NullPointerException("This property does not allow null!") else s
    }
}
Now, this is creating boiler-plate code, and we don't like boiler-plate code. Lets do this in a more reusable way:
import org.sgine.property.FilteredProperty

trait NullsAreBadFilteredProperty[T] extends FilteredProperty[T] {
    val filter = (value: T) => {
        if (value == null) {
            throw new NullPointerException("This property does not allow null!")
        } else {
            value
        }
    }
}
Now I can simply mix-in my new trait wherever I want to disallow nulls:
import org.sgine.property.MutableProperty

class Person {
    val name = new MutableProperty[String] with NullsAreBadFilteredProperty[String]
}

Transactional Properties


TransactionalProperty is the property equivalent of a database transaction. When a the property is created it maintains a reference to its initial value and the current value. At any time the value can be committed in order to roll forward the initial value to the current value or it may be reverted in order to roll back the current value to the initial value. Finally, when a TransactionalProperty is committed a PropertyTransactionEvent is thrown for the property that represents the original value and the new value.
import org.sgine.property.MutableProperty
import org.sgine.property.TransactionalProperty

class Person {
    val name = new MutableProperty[String]("") with TransactionalProperty[String]
}

Simple usage:
val person = new Person()
person.name := "John Doe"
person.name.revert() // Reverts the value back to ""
person.name := "Jane Doe"
person.name.commit() // Commits "Jane Doe"

Animation


Animation may be a little confusing of a name here since we're dealing with properties and not images, but AnimatingProperty works with a PropertyAnimator to allow "animation" from the current value to the newly applied value over time. Obviously this is of primary benefit in the case of a user-interface, but can be applicable to other uses as well.

Here is a simple example to animate linearly from 0.0 to 5.0 over five seconds:
import org.sgine.property.AnimatingProperty
import org.sgine.property.MutableProperty
import org.sgine.property.animate.LinearNumericAnimator

class Location {
    val x = new MutableProperty[Double](0.0) with AnimatingProperty[Double]
    x.animator = new LinearNumericAnimator(1.0)    // Move 1.0 per second
}

val location = new Location()
location.x := 5.0    // Begin animation from 0.0 to 5.0
location.x.waitForTarget()    // Convenience method to wait for target value to be reached
We're using LinearNumericAnimator, a built-in animator to work with Double properties, to animate 1.0 per second. If you are familiar with Flex or JavaFX this is similar in purpose to what they call "Effects". However, in those frameworks an Effect is defined apart from the property being modified and is simply activated upon it. Though this means writing explicit code for every movement you wish to make it is perfectly acceptable most of the time. However, this does create the potential problem of multiple effects being enacted on the same value at the same time. For example, a box is displayed in the center of the screen with two buttons. The first button moves the box to the left side of the screen and the second button moves the box to the right side of the screen. This is perfectly fine until you try hitting one right after another. If you don't add explicit support to cancel the first effect you will run into what I call "effect fighting". This is the scenario where two effects are trying to modify the same property to two different targets. The visual result of the box example is the box jumping to the left, then the right, then left, and so on with each effect attempting to update the position. Particularly in the case of Sgine, being a fully multi-threaded and thread-safe 3d engine this was of great concern. PropertyAnimator simplifies and abstracts the process, preventing effect fighting from occurring.

Consider another scenario. In the Location class we created above, if it were being managed in a layout manager of some sort, the layout manager wouldn't necessarily know anything about animation. By virtue of the fact that the layout manager modifies the "x" property, instead of immediately jumping to the new position, animation would occur.

LinearNumericAnimator is just one built-in PropertyAnimator. EasingNumericAnimator similarly works with Double properties, but uses easing functions instead of linear motion. Numbers are not the only things that can be animated though. The EasingColorAnimator works similarly to EasingNumericAnimator, but works on Colors. At the time of this writing those are the only built-in PropertyAnimators, but writing your own PropertyAnimator is a simple matter of providing your own implementation of the following method signature:
def apply(current: T, target: T, elapsed: Double): T

Easings with animation is generally more elegant than simple linear animation. Sgine has a full listing of easing functions supported:
  • BackIn / BackOut / BackInOut
  • BounceIn / BounceOut / BounceInOut
  • CircularIn / CircularOut / CircularInOut
  • CubicIn / CubicOut / CubicInOut
  • ElasticIn / ElasticOut / ElasticInOut
  • ExponentialIn / ExponentialOut / ExponentialInOut
  • LinearIn / LinearOut / LinearInOut
  • QuadraticIn / QuadraticOut / QuadraticInOut
  • QuarticIn / QuarticOut / QuarticInOut
  • QuinticIn / QuinticOut / QuinticInOut
  • SineIn / SineOut / SineInOut

This concludes part 1 of this tutorial. Please continue on to part 2 for the conclusion.

Tuesday, August 31, 2010

The Advantages of Using Properties Instead of Getters/Setters in Java and Scala

There have been a few concepts I've been pushing for most of my programming career, and one of the top items on that list is Properties. This is a topic I've been meaning to delve into for a while, and have previously, but as this is an incredibly important part of the core of Sgine I would like to take some time to state the case for Properties. This post is all about why Properties are useful and ultimately why Sgine uses them. The next post, Properties - Tutorial, will go into great detail about how to use Properties within the context of Sgine. Properties as a term is bandied about in many different forms, so first a definition is in order.

Definition


In the context of this discussion a Property is the concept of a wrapper class around a value as an alternative to the standard private field, public getter/setter. For example in Java:
public class Person {
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

person.setName("John Doe");
String name = person.getName();

The property alternative:
public class Person {
    public final name = new Property<String>(null);
}

person.name.set("John Doe");
String name = person.name.get();

A basic Property class in Java might look something like:
public class Property<T> {
    private T value;

    public void set(T value) {
        this.value = value;
    }

    public T get() {
        return value;
    }
}

Or in Scala:
class Person {
    private var _name: String = _

    def name = _name

    def name_=(name: String) = _name = name
}

person.name = "John Doe"
val name = person.name

The property alternative:
class Person {
    val name = new Property[String](null)
}

person.name := "John Doe"
val name = person.name()

A basic Property class in Scala might look something like:
class Property[T] {
    private var value: T = _

    def :=(value: T) = this.value = value

    def apply() = value
}

Since this blog is about Sgine, a 3d engine in Scala, I will be showing all further example code only in Scala though much of this still applies directly to Java.

Advantages


This is all well and good, but for all practical appearances it's about the same as classic getter/setter pattern. Why would you want to break convention and use Properties instead?

In the examples above there isn't much practical difference between the two methodologies. Performance-wise they are identical. Properties reduce the amount of code in your class by a pretty large margin if you consider one line:
val name = new Property[String](null)

Instead of three (or seven in the case of Java):
private var _name: String = _
def name = _name
def name_=(name: String) = _name = name

However, the typical response here is that with today's IDEs they will generate the getter/setters for you automagically, so what does that matter? To some degree I agree with this, but it is still clutter added to your classes that make managing your source code that much more complicated down the road. I will agree though that this in and of itself is not a convincing reason to break convention so lets get on to the real reason.

Ultimately it comes down to one major reason to use the Property concept instead of methods, and that is encapsulation. Given the above Person example with a "name", how would you handle a check upon assignment to make sure the name is no more than 255 characters, and if it is, to chop off the extra characters?

Perhaps something like:
class Person {
    private var _name: String = _

    def name = _name

    def name_=(name: String) = {
        val filtered = ...filter name...
        _name = filtered
    }
}

That's simple enough, but what if you want to add an "address" field as well and limit it to 255 characters? Sure, you can simplify by creating a "filter" method you can invoke, but no matter how you swing it, you end up with boiler-plate code to accomplish your task. The reason this happens is because methods don't have the ability to encapsulate and extend functionality the way that an object does. So for the above example I could simply create a FilteredProperty trait that can be mixed in:
trait FilteredProperty extends Property[String] {
    abstract override :=(value: String) = {
        val filtered = ...filter value...
        super.:=(filtered)
    }
}

Now you simply make a very slight change to your person class to get the benefits of filtering:
class Person {
    val name = new Property[String](null) with FilteredProperty
}

Hopefully you are beginning to see the advantages here. In order to add functionality to your simply extend Property functionality to provide what you want and then mix it together in your resulting Property instance. Not only does this remove any need for boilerplate code, but it makes reading the source code for classes extremely easy as a single line of code describes the make-up of that property.

Here are a few examples of things you can do well with Properties:
  • Events: Adding event listeners to a property is one of the most common uses for a Property system as event handling in a standard Bean scenario involves a lot of boiler-plate code. Here's a simple example of usage:
    person.name.listeners += nameChanged _
    
    private def nameChanged(evt: PropertyChangeEvent[String]) = {
        ... property has changed ...
    }

    As is hopefully obvious, any changes to person.name will result in the invocation of the nameChanged method.
  • Binding: Synchronizing two properties together via binding is probably the second most common reasons Properties are used. This is something that takes quite a bit of effort to support, but by leveraging Properties the functionality can be written once and then re-used everywhere desired. Here's a simple example of usage:
    person1.name bind person2.name

    Sure, that's incredibly simple, but now any changes to person2's name will result in person1's name being updated as well.
  • Translation: The ability to translate incoming values is a very broad topic, whether you are converting Strings to Ints, translating to another language upon set, or simply modifying all applied data to follow a specific standard Properties can provide all of the functionality by simple extension and mix-in.
  • Filtering: Applying a filter may represent limiting of a String to 255 characters as discussed above, or it may include throwing an Exception if invalid data is attempted to be passed (ex. Attempting to set null on a Property that should not be null).
  • Transactions: Simple transaction support may consist of an uncommitted value along with commit and rollback methods. This would allow simple management of objects in a user-interface and the ability to know if the object has uncommitted values and what they are so you are only applying changes to the database instead of sweeping updates.
  • Animation: Also called "adjusters", this is the ability to move from one value to another over time. This is most commonly applied to numbers. For example, a AnimatingProperty trait may start at 0.0 but when the value is set to 100.0 instead of applying it directly, it is applied over time and possibly with an easing function.
  • Delegation: This allows the ability delegate getting/setting functionality to another method, function, or value.

There is a great deal more that can be done with Properties, but this is hopefully a nice glimpse to what is possible.

History


As much as I'd love to claim responsibility for the idea of properties, alas, it is not my own and here are a few URLs to other posts about properties (including some older ones from me):

http://joda-beans.sourceforge.net/
http://www.javalobby.org/java/forums/t88090.html?start=50#92123353
http://www.javalobby.org/java/forums/t90756.html
http://www.javalobby.org/java/forums/m92123242.html
http://www.matthicks.com/2009/06/have-beans-been-holding-us-back.html
http://www.matthicks.com/2009/07/death-of-beans.html

Saturday, August 28, 2010

Stressed - Asynchronously

In a previous post I discussed the improvement in performance to be able to display 1600 cubes on the screen at a time at 32fps. It has been quite a while since that post, and until recently I've been busy with infrastructure cleanup and changes and just recently cycled back around to take another look at performance.

One of the main goals of Sgine from the beginning has been to be a multi-threaded 3d engine. However, early on there were some problems with updating content asynchronously that were causing visual issues so I modified all non-renderer updates to occur in the rendering thread (like every other 3d engine out there). After remembering that I had never switched this back over (yeah, just took a single line of code: Updatable.useWorkManager = true), I re-ran the stress test:



Yes, you read that right, I went from 32fps all the way up to 296fps. That's a pretty substantial jump if I do say so myself. There are additional tweaks I can make to make it even faster I think, but I'll save that for another day.

While we're on the topic of multi-threading 3d engines I'd like to share another recent development. As anyone ever developing multi-threaded support in a 3d engine is aware, there are many times you find yourself outside of the rendering thread, but you need to invoke some rendering logic. This was a big problem in jME and Renanse (Joshua Slack) and I came up with the GameTaskQueue that would allow you to inject "work" to be done into a queue to be done later in the rendering thread.

To some degree I make use of the same concept in Sgine, but have created a trait "org.sgine.work.Worker" to represent this functionality. Either a Function0[Unit] or curried function can be passed to invokeLater or invokeAndWait like so:

renderer.invokeLater {
    glPolygonMode(GL_FRONT, GL_POINT)
}

This is on par, but slightly easier to read than passing a Runnable to a queue, but still not too far off. However, I remember being incredibly frustrated in jME having to do this all the time when I needed to inject some logic into the renderer. Now, in Sgine that shouldn't usually be necessary as its purpose is to abstract the rendering layer, but still I wanted to take this a step further (primarily for internal use).

So here's a real-world example of a problem that was created by asynchronous updates. In the Debug trait it adds a keyboard listener to do specific things upon key press. For example, hitting Escape will shutdown the renderer. This shouldn't be a problem as the Renderer.shutdown() method can be invoked asynchronously with any trouble, but unfortunately I have no reference to the current Renderer, so I have to use Renderer() to get the ThreadLocal Renderer. Obviously if keyboard events are being thrown outside of the renderer thread this causes a problem.

So, in an effort to simplify this process, a new feature has been added to EventHandler to allow a "worker" to be specified. If a worker is specified then all calls to invoke the wrapped listener will be "invokeAndWait" through that worker.

In the case of Debug:

Keyboard.listeners += EventHandler(handleKey, ProcessingMode.Blocking)

Now becomes:

Keyboard.listeners += EventHandler(handleKey, ProcessingMode.Blocking, worker = renderer)

From now on I don't have to worry about finding the right renderer and then invokeAndWait within that renderer for anything within the handleKey function, I can rely on the fact that handleKey is always going to be run within the rendering thread.

Saturday, July 31, 2010

Writing Tetris

I'm currently in the process of writing a couple small games in an effort to use Sgine for some real-world game development in order to fill in any wholes and evaluate how easy it is to use in a complete application. The first simple game on my agenda is Tetris. I'd say I'm about half-way finished writing it, and I think it's coming along pretty well:



As you can see I'm using 3d cubes to represent pieces and though the game itself is still played on two dimensions the appearance is in 3d slightly translucent and rotated on the x-axis in order to give it a little more depth. I'll post a link to play the game once it is finished, but I know many people have asked if there are any practical examples of Sgine and I just wanted to send out this note to let everyone know that there will be soon. :)

Also, you can't see it from the screenshot obviously, but I have the original Tetris theme playing in the background on loop. Oh, how it takes me back to playing on the Gameboy as a kid. :)

Sunday, July 25, 2010

Performance Update

I mentioned previously that I was working on performance tweaks to Sgine and I referenced a performance test of 400 cubes rotating and animating back-and-forth on the screen at 38fps.

Since that post I have made some pretty major updates to the backing renderer to increase performance. There's still quite a bit left that can be tweaked, but at this point I'm much more confident in the overall performance of the engine but wanted to outline a few of the changes made to the system and the current results.

First, I was previously using render.RenderImage, that basically just displays a textured quad on the screen with immediate mode rendering. This has been changed to rely on render.shape.Shape class that allows any OpenGL shape to be represented with vertices with triangles, quads, etc. The new Shape class also automatically detects whether VBO is supported and will use that if available over immediate mode. I plan to add additional support for GLSL in the future, but at the moment my focus is the best compatibility and working upwards.

Next, I created a new ui.Box class that represents a modifiable, texturable box on the screen. Previously the cubes being displayed were represented by six distinct RenderImages backed against the same texture.

Finally, I've added the ComponentInstance class I mentioned in my last post to allow instancing rather than creating completely new cubes each time.

The results of these changes were a pretty good bump in performance:



Now, keep in mind that framerates are not linear, so this is a pretty substantial improvement over the 38fps I was previously getting.

To prove this I added a few more boxes to the scene (1600 to be exact) to get my framerate back into the 30s:



The new source code looks a bit different from the previous stress test, but pretty easy to read I think:

package org.sgine.ui

import org.sgine.core.Resource

import org.sgine.easing.Elastic

import org.sgine.effect._

import org.sgine.property.animate.EasingNumericAnimator
import org.sgine.property.animate.LinearNumericAnimator

import org.sgine.render.Debug
import org.sgine.render.RenderSettings
import org.sgine.render.StandardDisplay

import org.sgine.ui.ext.AdvancedComponent

import scala.math._

object TestStressBoxes extends StandardDisplay with Debug {
 override val settings = RenderSettings.High
 
 def setup() = {
  var box: Box = null
  for (row <- 0 until 40) {
   for (column <- 0 until 40) {
    val y = (row * 30.0) - 350.0
    val z = (column * 90.0) - 1800.0
    if ((row == 0) && (column == 0)) {
     box = createBox(y, z, 0.05)
    } else {
     createInstance(box, y, z, 0.05)
    }
   }
  }
 }
 
 def createBox(y: Double, z: Double, scale: Double) = {
  val box = new Box()
  box.scale.set(scale)
  box.location.set(0.0, y, z)
  box.source := Resource("sgine_256.png")
  
  animate(box)
  
  box.update(0.0)
  scene += box
  
  box
 }
 
 def createInstance(component: Component, y: Double, z: Double, scale: Double) = {
  val instance = ComponentInstance(component)
  instance.scale.set(scale)
  instance.location.set(0.0, y, z)
  
  animate(instance)
  
  instance.update(0.0)
  scene += instance
  
  instance
 }
 
 private def animate(component: AdvancedComponent) = {
  component.rotation.x.animator = new LinearNumericAnimator(2.0)
  component.rotation.y.animator = new LinearNumericAnimator(2.0)
  component.rotation.z.animator = new LinearNumericAnimator(2.0)
  component.location.x.animator = new EasingNumericAnimator(Elastic.easeInOut, 3.0)
  
  component.rotation.x := Double.MaxValue
  component.rotation.y := Double.MaxValue
  component.rotation.z := Double.MaxValue

  // Move the cube back and forth perpetually on the x-axis
  val me0 = new PauseEffect(random * 2.0 + 0.5)
  val me1 = new PropertyChangeEffect(component.location.x, -400.0)
  val me2 = new PropertyChangeEffect(component.location.x, 400.0)
  val move = new CompositeEffect(me0, me1, me2)
  move.repeat = -1
  move.start()
 }
}

This could be cleaned up more, but should give you an idea of how simple it is to fill a scene up with boxes. :) I'd like to make one last note on this test that you can't see unless you actually run it. The previous test took around 20 seconds to asynchronously fully load all cubes on the screen. Since I'm using ComponentInstance that time has dropped to about one second to fully load on the screen. This is a drastic improvement in scene load-time. Now it's time to get back to work on functionality.

Saturday, July 24, 2010

Instancing

I've mostly been working on performance and internal tweaks to Sgine lately, but one of the things I've recently added that is both a performance benefit and a really "nice-to-have" for game development particularly is what I call "instancing". In a game you often have many instances of an object on the screen at any given time whether it's a wall, a character, or something else it can be really performance intensive and a waste of memory to have each instance completely represented independently of the others, particularly for complex objects. To help resolve this I've created ComponentInstance to allow creation of a Component and then re-use without all the baggage.

For example, see the following code snippet:

package org.sgine.ui

import org.sgine.core.Color
import org.sgine.core.Resource

import org.sgine.render.Debug
import org.sgine.render.StandardDisplay

object TestInstancing extends StandardDisplay with Debug {
 def setup() = {
  val image = new Image(Resource("puppies.jpg"))
  scene += image
  
  val i1 = ComponentInstance(image)
  i1.location.set(-300.0, 200.0, 5.0)
  i1.scale.set(0.4)
  i1.alpha := 0.5
  i1.color := Color.Red
  scene += i1
  
  val i2 = ComponentInstance(image)
  i2.location.set(300.0, 200.0, 5.0)
  i2.scale.set(0.4)
  i2.alpha := 0.5
  i2.color := Color.Green
  scene += i2
  
  val i3 = ComponentInstance(image)
  i3.location.set(-300.0, -200.0, 5.0)
  i3.scale.set(0.4)
  i3.alpha := 0.5
  i3.color := Color.Blue
  scene += i3
  
  val i4 = ComponentInstance(image)
  i4.location.set(300.0, -200.0, 5.0)
  i4.scale.set(0.4)
  i4.alpha := 0.5
  scene += i4
 }
}

The result of the above code is this:



This also makes it easy to modify one component and reflect it in all instances. There's a lot more functionality in the pipeline that will help increase the performance of Sgine, but unfortunately most of it is internal and not as cool to look at in a blog post. :)

Sunday, July 18, 2010

Performance and Shapes

The functionality is really starting to come together on Sgine, but the performance has been a bit lower than I had hoped for large scenes. For simple games and business applications Sgine is performing quite well, but it's definitely not yet ready to write a first-person shooter on yet.

I've spent a bit of time doing performance tweaking and optimizations with YourKit and the performance is getting better, but still not where I'd like to see it. Right now I've got 400 cubes (which is made up of four independent Images for greater complexity) rotating and animating back and forth across the screen via easing effect at 38fps:



Not terrible, but over the next few weeks I'm hopeful I can get 4,000 cubes rendering at over 60fps.

Another quick note is that I've created a little Shape system in Sgine that will hopefully eventually be the core of all rendering as it auto-detects and uses additional capabilities of the video card for better performance. Additionally, I've added support for java.awt.Shape to ShapeData to draw nifty things like vector-text directly from a java.awt.Font to the screen. This is not the Shape-to-Texture cheating that most of the other engines do, this is direct to screen via tesselation. I've turned off any anti-aliasing so you can see it for yourself:



I've still got more work before I'm finished with the new Shape system, but once it is done I think this should help me get to the framerates I'm looking for.

Friday, July 16, 2010

Major Changes

I've been pretty quiet lately, but it's because I've been working with Aleksey Nikiforov (lex) on migrating Sgine to using Simplex3d instead of our built-in math library. This has been a pretty long endeavor and lots of work from both Lex and myself have gone into the migration, but I believe the effort has paid off. This morning I merged the simplex3d branch back into 'default' and we've now got better performance along with a much more powerful math library to back against.

There have been a lot of other changes that have been introduced while this migration was happening, but I'll save that for another post.

For now, if you're interested in seeing the merge changes from 'simplex3d' to 'default' you can see it here: http://build.sgine.org/job/sgine/74/changes.

Wednesday, June 23, 2010

JLaunch + Sgine

As I mentioned in my previous post I've been working on a simplified deployment system for Java applications and I've made some pretty good strides. To that end I wanted to share my current progress by finally posting a working applet here to show:



Using a bit of JavaScript the applet will launch when you click on the static image. This is still a very early version, but my goal is to release JLaunch as an open-source project that provides a wizard to simplify creating deployments. The system currently supports two methods of launching. The first is a static void main(args) method that it invokes that gives over complete control to display a new Frame or whatever it is configured to do. The second is the referenced class providing a "createCanvas" method that returns a java.awt.Canvas instead that gets put into the applet for you upon instantiation. The latter instance is what is being used in the above example and is implemented by default in StandardDisplay, so any classes that extend that don't even have to think about it.

For example, see the code for the TestImage class being used:

package org.sgine.ui

import org.sgine.core.Resource

import org.sgine.render.Debug
import org.sgine.render.StandardDisplay

object TestImage extends StandardDisplay with Debug {
 def setup() = {
  val component = new Image(Resource("puppies.jpg"))
  scene += component
 }
}

I also inherit Debug which disables vertical-sync and shows the framerate in the top-left of the screen. To sum up, the above two lines of logic can be launched as an application (since StandardDisplay provides a main method that is inherited) or as an applet via JLaunch. Pretty awesome huh? :)

One last noteworthy item is that the jlaunch.jar is 14kb and the pack200 version is a total of 5kb. This, I believe, is a good representation of what the startup time of applets should be.

Wednesday, June 16, 2010

Layout Management

For any UI application layout management is an absolute essential. In 3D game development I have yet to see any sort of layout management and though I can think of a few uses they are pretty few and far between. However, with the goals of Sgine to provide both a 3D UI as well as a full scenegraph infrastructure layout management is a very important thing.

What's particularly cool about layout management in Sgine is that it's not just for UI elements and it's not just for vertical and horizontal. That's right, you can use layout managers to lay out 3D objects in 3D space.

The layout management infrastructure is now in place, but still has a long way to go to provide a full set of advanced layout techniques. For now, here's a simple example laying out two Buttons:

package org.sgine.ui

import org.sgine.core.Direction

import org.sgine.render.StandardDisplay

import org.sgine.ui.layout.BoxLayout

object TestLayout extends StandardDisplay {
 def setup() = {
  val container = new LayoutContainer()
  container.layout := BoxLayout(Direction.Vertical, 10)
  container += new Button("Test Button 1")
  container += new Button("Test Button 2")
  scene += container
 }
}

What do you get for those five lines of logic? This:



You are not required to specify the layout as it will default to BoxLayout(Direction.Vertical, 0), but in order to show how easy configuring the layout function I decided to show a custom example. Custom layout functions can be provided that simply follow: Function1[NodeContainer, Unit].

Tuesday, June 15, 2010

Concise and Powerful

One of my biggest complaints and one of the things I've been criticized about most is my hatred for the complexities of using the majority of 3D engines today. To this end I've strived in Sgine to provide a much more simplistic and concise engine without sacrificing the power you would expect from a 3D engine.

When I was a developer on the jME (http://www.jmonkeyengine.com) project it is what led me to write "StandardGame" as far too commonly developers would end up with basically the same "Game" implementation for all their games, but it either consisted of a lot of copy and paste from other projects or a lot of re-writing the same code each time a new project was created.

If you look at previous posts the code has always been moderately simple and no more than a dozen or so lines of code to accomplish a basic task. However, I still had visions for improving further.

Perhaps I've gone a bit overboard in my agenda to simplify, but I've created a new trait in Sgine called "StandardDisplay" that is the spiritual successor to the ideas I put forth in jME years before. With Scala and Sgine a lot of possibilities for simplification have been opened up that were never possible before, such as putting the main method in a trait so it need not be explicitly defined. Further, one of the big problems with JRE applications today is deployment. Whether you want an Applet, a WebStart application, a desktop application, or all three it is a great deal of pain to get the end result you want. One of the goals of StandardDisplay is to be able to simply extend and execute in any display model you desire. Couple this with the idea of a deployment generation system I have yet to write and deployment of applications can be a simple afterthought instead of a major headache holding you back from getting your projects out.

Okay, I've droned on long enough without some actual code to show. If you've read this blog from the beginning you'll remember the very first post I made with an actual example with the following code to display an image of my dogs:

package org.sgine.render

import org.sgine.math.Matrix4

import javax.imageio._

import org.lwjgl.opengl.GL11._

object TestRenderer {
 def main(args: Array[String]): Unit = {
  val r = Renderer.createFrame(1024, 768, "Test Renderer")
  
  val t = new Texture(700, 366)
  TextureUtil(t, ImageIO.read(getClass.getClassLoader.getResource("resource/puppies.jpg")), 0, 0, 700, 366)
  
  val m = Matrix4().translate(z = -1000.0)
  val i = Image(t)
  val fps = FPS(1.0)
  
  r.renderable := RenderList(MatrixState(m) :: i :: fps :: Nil)
  
  println("Renderer started!")
 }
}

That concept has firmed up a lot since then with the scenegraph system and the UI package to more recently look like:

package org.sgine.ui

import org.sgine.core.Resource

import org.sgine.render.Renderer
import org.sgine.render.scene.RenderableScene

import org.sgine.scene.GeneralNodeContainer
import org.sgine.scene.ext.ResolutionNode

object TestImage {
 def main(args: Array[String]): Unit = {
  val r = Renderer.createFrame(1024, 768, "Test RenderScene")
  
  val scene = new GeneralNodeContainer() with ResolutionNode
  scene.setResolution(1024, 768)
  
  val component = new Image()
  component.source := Resource("puppies.jpg")
  scene += component
  
  r.renderable := RenderableScene(scene)
 }
}

Though much more concise and simplified I still was not satisfied. After all, I just wanted to display a picture of my puppies on the screen. Enter StandardDisplay:

package org.sgine.ui

import org.sgine.core.Resource

import org.sgine.render.StandardDisplay

object TestImage extends StandardDisplay {
 def setup() = {
  val component = new Image(Resource("puppies.jpg"))
  scene += component
 }
}

That's right, two lines of actual logic code to display an Image with puppies. Yes, this technically could have been reduced to a single line, but the goal was concise, not showing how I used to write code in Perl. ;)

This can be executed as an application since StandardDisplay trait contains a "main" method that calls "start" and the only requirement is that a "setup" method be implemented. You can go much further than this if desired to customize and configure how and what you want to display but this is all that is required to get going.

There is still a lot of work to be done to support Applets, WebStart, etc. but the core is functional and pretty impressive if I do say so myself. :)

Sunday, June 13, 2010

MediaPlayer Component

Getting JMC from JavaFX 1.3 to work within Sgine took a bit longer than I anticipated. In JavaFX 1.2 it was a simple matter of calling paintVideoFrame and using a BufferedImage to draw onto and then convert to a texture. Fortunately for performance in JavaFX 1.3 they changed to working with NIO buffers instead, but unfortunately that created a much bigger headache trying to figure out how to access and properly use it since there is absolutely no documentation and the source code is not freely available. However, after several days of poking around it has finally paid off. There are still some optimizations that should be done but on my machine I'm able to watch H.264 video at 4,000fps in synchronous mode (direct rendering in OpenGL) and 5,200fps in asynchronous mode (pushing data to the buffer in another thread via PBO).

Here's a screenshot of the working example:


Here's the source required to run the video:
package org.sgine.ui

import org.sgine.core.Resource

import org.sgine.render.Renderer
import org.sgine.render.scene.RenderableScene

import org.sgine.scene.GeneralNodeContainer
import org.sgine.scene.ext.ResolutionNode

object TestMediaPlayer {
 def main(args: Array[String]): Unit = {
  val r = Renderer.createFrame(640, 480, "Test MediaPlayer")
  
  val scene = new GeneralNodeContainer() with ResolutionNode
  scene.setResolution(640, 480)
  
  val component = new MediaPlayer()
  val url = new java.net.URL("http://sun.edgeboss.net/download/sun/media/1460825906/1460825906_2956241001_big-buck-bunny-640x360.flv")
  component.source := Resource(url)
  scene += component
  
  r.renderable := RenderableScene(scene)
  
  component.play()
 }
}

As always the goal is to keep the API as simple as possible and hopefully 27 total lines of code is simplistic enough. :)

There's still much left to do as far as introspection and control of video playing as well as controls to allow user interaction with the player, but we've finally got a fast and reliable means of playing all popular audio and video formats and I will probably divert back to more important work for a while. :)

Wednesday, June 9, 2010

Video Player

I've been pretty busy lately and haven't had time to work on Sgine as much as I'd liked, so I figured I needed to have something pretty awesome to show for my next post. Hopefully video playing is still considered awesome as that's the best I could do.

I'm leveraging the JMC system that JavaFX uses for video playing and integrating it to render directly to LWJGL.

It's not really ready for prime-time as I've got a lot of things still to do to increase the framerate and integrate it as an actual component, but for now I have a screenshot with the promise of more to come soon:

Saturday, May 22, 2010

ResolutionNode

I'm back from a week long cruise to the Caribbean without cell phones, computers, or internet access. It was a great break from technology, but now I'm back, refreshed, and ready to crank out more functionality into Sgine.

What I have today is called ResolutionNode. If you look back at all the blogged examples below you'll notice all the 'z' translation stuff on the components. The reason for that is because Sgine (and OpenGL generally) is configured to have 'z' at 0.0 have a distance of -1.0 to 1.0 both vertically and horizontally. Further, anything between 0.0 and -1.0 (negative to back further into the screen) is clipped for mathematical precision reasons. So by pushing the the components to something like -1000.0 for 'z' causes it to appear much smaller because its depth is so far back into the projection.

This is fine for games and general 3D applications, but can be a pain in the neck when you want to have a normal graphics-based UI and you're expecting a specific resolution (e.g. 1024x768) to design graphics and layout for. To this end I have created a trait called ResolutionNode. It gives the ability to specify a resolution (e.g. 1024x768) and modifies the world matrix for that Node to properly display that resolution to fit to the screen. Not only does this give you the benefit of managing the resolution for the screen, but it also keeps you from having to worry about the *actual* resolution as this will scale-to-fit so even if you are running 1920x1200 resolution if you specify 1024x768 internally you'll end up with everything being stretched to fit.

This is actually part of a larger UI design concept I've been developing that I'll go into more on as the functionality is finalized in Sgine, but for now I give you my example.

The following code takes a 1024x768 image and a 640x480 image and displays them overlayed on top of each other. The cool thing here though is that you can see that using a ResolutionNode container for each I am able to see both of them at the exact same size.

package org.sgine.ui

import org.sgine.core.Color
import org.sgine.core.Resource

import org.sgine.render.Renderer
import org.sgine.render.scene.RenderableScene

import org.sgine.scene.GeneralNodeContainer
import org.sgine.scene.ext.ResolutionNode

object TestResolution {
 def main(args: Array[String]): Unit = {
  val r = Renderer.createFrame(1024, 768, "Test Resolution")
  r.verticalSync := false
  
  val scene = new GeneralNodeContainer()
  
  val r1024 = new GeneralNodeContainer() with ResolutionNode
  r1024.setResolution(1024.0, 768.0)
  scene += r1024
  
  val c1024 = new Image()
  c1024.source := Resource("1024.jpg")
  c1024.alpha := 0.5
  r1024 += c1024
  
  val r640 = new GeneralNodeContainer() with ResolutionNode
  r640.setResolution(640.0, 480.0)
  scene += r640
  
  val c640 = new Image()
  c640.source := Resource("640.jpg")
  c640.alpha := 0.5
  r640 += c640
  
  r.renderable := RenderableScene(scene)
 }
}

The two images I'm using are:



and:



The resulting screenshot is as follows:

Sunday, May 2, 2010

ColorNode and Render Sorting

I followed the same approach for ColorNode as I did for MatrixNode and now have the ability to define hierarchical color and alpha in Sgine. With this addition I started playing with TestCube to see how well it worked translucent. Unfortunately because I was not doing any sorting on the render list I end up with some undesirable effects:



With a simple modification to sort based on depth I now get this:



I'm doing the sort per render, which I'm sure is incredibly inefficient, but my framerate dropped from 3000fps to 2900fps in this example. I need to spend some time and make it only sort upon change, which in the test cube scenario would probably not make a lot of difference in performance since it's swapping positions every few frames, but will increase the efficiency in less frequently changing scenes.

Saturday, May 1, 2010

MatrixNode Awesomeness!

There were several things I was hoping to get accomplished today that didn't get done because I got sidetracked on another task that ended up taking significantly longer than I had anticipated. My initial implementation of Node / Component support for Matrix4 was spotty and I wasn't very happy with it, so I took the time today to refactor it and make it into a much more powerful and simplified architecture.

For those of you that have actually used the scene support in Sgine will be aware, the scenegraph architecture is extremely abstract and is designed to avoid implications towards a specific use and allow multiple uses within the same scenegraph. For example, a NodeContainer could possibly contain physics information, sound/music information, visual rendering information, etc. while each part being completely separate and independent from the other. The level at which I'm able to accomplish this is almost entirely due to the awesomeness that is Scala, but to that end abstractions often make it difficult to architect advanced uses without making system extremely complicated. For example, if I want to have my root NodeContainer define matrix information to translate 'z' to -200.0, meaning that all children will receive that it can be problematic to support if nodes between don't also provide matrix support. However, that is the difficulty I solved today. :)

I've created a simple trait "MatrixNode" that contains a "localMatrix" and a "worldMatrix". The "localMatrix" can be manipulated to represent the local translation, rotation, scale, etc. and upon change will invalidate the "worldMatrix" causing it to get updated to the parent's "worldMatrix" (walking up the scenegraph as necessary) multiplied against the "localMatrix".

See the following example:
package org.sgine.ui

import org.sgine.core.Color
import org.sgine.core.Resource

import org.sgine.easing.Linear

import org.sgine.render.Renderer
import org.sgine.render.scene.RenderableScene

import org.sgine.scene.GeneralNodeContainer
import org.sgine.scene.MatrixNode

object TestScene {
 def main(args: Array[String]): Unit = {
  val r = Renderer.createFrame(1024, 768, "Test RenderScene")
  
  val scene = new GeneralNodeContainer()
  
  val container1 = new GeneralNodeContainer() with MatrixNode
  container1.localMatrix().translate(0.0, 0.0, -200.0)
  scene += container1
  
  val container2 = new GeneralNodeContainer() with MatrixNode
  container2.localMatrix().translate(0.0, 0.0, -500.0)
  container1 += container2
  
  val container3 = new GeneralNodeContainer()
  container2 += container3
  
  val component = new Image()
  component.source := Resource("puppies.jpg")
  component.color := Color(1.0, 1.0, 1.0, 0.5)
  component.location.z := 100.0
  container3 += component
  
  r.renderable := RenderableScene(scene)
 }
}

This is a pretty simple example. As you can see there are four containers (scene, container1, container2, and container3) and two of them mix-in "MatrixNode" in order to specify a translation (container1 and container2). Finally, there is a Image "component" that defines its own location.z. As a result "component" will render at a "z" translation of -600.0 (-200.0 + -500.0 + 100.0). Notice that although "container3" is between "container2" and "component" it is still applied. This allows extremely powerful control of the contents of the scenegraph while maintaining a very simple abstract feel.

Hopefully in the coming weeks you'll see much more functionality like this making its way into the system. In fact, I believe I'm going to have to write something along these lines for Color in order to properly mix colors hierarchically for OpenGL.

Saturday, April 24, 2010

Label, Scale9, FontManager, and Resource

Yes, this is my third post today, but it's Saturday and I'm cranking through code now that I've gotten over the mouse-picking hurdle!

I have created a new component "Label" that is moderately self-explanatory, but represents a single-line of text. With this Resource comes to fruition as a simple lookup call "Resource(resourceName)" that will find a resource in the defined resource paths (defaults to look in "resource" path). Additionally I have created a FontManager that simplifies the management of fonts in the system. I have plans in the long-run to create a bitmap-font generator from AWT fonts, but for now getting a font is as easy as "FontManager("Arial")" presuming there's an AngelCode font definition in the Resource lookup path by the name of "Arial.fnt".

See the following test of Label:

package org.sgine.ui

import scala.io.Source

import org.sgine.input.event.MousePressEvent

import org.sgine.render.Renderer
import org.sgine.render.font.FontManager
import org.sgine.render.scene.RenderableScene

import org.sgine.scene.GeneralNodeContainer

object TestLabel {
 def main(args: Array[String]): Unit = {
  val r = Renderer.createFrame(1024, 768, "Test RenderScene")
  
  val scene = new GeneralNodeContainer()
  val component = new Label()
  component.location.z := -500.0
  component.font := FontManager("Franklin")
  component.text := "Hello World!"
  scene += component
  
  r.renderable := RenderableScene(scene)
 }
}

Even more exciting is Scale-9 (a.k.a nine-slice) support that opens up more advanced skinning functionality and in the short-run allows creation of pretty buttons; bet you can guess what's up next. ;)

Anyway, here's a quick test using the new Scale9 component:

package org.sgine.ui

import org.sgine.core.Resource

import org.sgine.render.Renderer
import org.sgine.render.scene.RenderableScene

import org.sgine.scene.GeneralNodeContainer

object TestScale9 {
 def main(args: Array[String]): Unit = {
  val r = Renderer.createFrame(1024, 768, "Test Scale-9")
  
  val scene = new GeneralNodeContainer()
  
  val component = new Scale9()
  component(Resource("scale9/windows/button/hover.png"), 3.0, 3.0, 4.0, 5.0)
  component.width := 200.0
  component.height := 50.0
  component.location.z := -500.0
  scene += component
  
  r.renderable := RenderableScene(scene)
 }
}

Here's a screenshot of the application:



That's using a pretty Windows 7 skinned button in a hover state.

Component Mouse Events

Now that I've got mouse-picking all figured out things are moving swiftly forward. I have created a new "bounding" package in sgine to support hit testing for mouse events and collision detection in the future. One of the awesome things about Scala's mix-ins is that I can modularize functionality down to a few traits that make up specific functionality to allow users of the engine to take on as much or as little of the system as they want. To this end I've created two classes: MatrixPropertyContainer (name to change to MatrixObject) and BoundingObject. MatrixPropertyContainer represents an immutable property "matrix" that returns a mutable Matrix4 and BoundingObject similarly contains an immutable property "bounding" that returns a Bounding instance.

In RenderableScene I listen for events on Mouse, walk through the NodeView for my scene matching Nodes that have both of these traits and then do a hit-test with them. The result is shown in the test below:

package org.sgine.ui

import org.sgine.core.Resource

import org.sgine.event.EventHandler

import org.sgine.input.event.MouseEvent

import org.sgine.render.Renderer
import org.sgine.render.scene.RenderableScene

import org.sgine.scene.GeneralNodeContainer

object TestMousePicking {
 def main(args: Array[String]): Unit = {
  // Create the Renderer
  val r = Renderer.createFrame(1024, 768, "Test Mouse Picking")
  
  // Create a mutable scene
  val scene = new GeneralNodeContainer()
  
  // Create an image to show the puppies
  val component = new Image()
  component.location.x := -200.0
  component.location.z := -500.0
  component.scale.x := 1.5
  component.rotation.y := Math.Pi / -4.0
  component.source := Resource("resource/puppies.jpg")   // 700x366
  scene += component
  
  // Add our scene to the renderer
  r.renderable := RenderableScene(scene, false)
  
  // Add a listener to listen to all mouse events to the picture
  component.listeners += EventHandler(mouseEvent)
 }
 
 // The method that is invoked when a mouse event occurs on the picture
 private def mouseEvent(evt: MouseEvent) = {
  println("MouseEvent: " + evt)
 }
}

Though adding a listener to mouse events is a one-line call the underlying functionality remains modular and optional to rendering functionality in the application giving the benefits of simple functionality in classes that make use of it, and trimmed down explicit functionality in those classes that do not. The mouse event system dispatches "press", "release", "move", and "wheel" events. I have on my todo to incorporate "over" and "out" events as well.

Mouse Picking

The reason for the delay since the last post has been the fact that I've been bogged down with mouse-picking for a while. Getting the math correct to properly handle ray-casting to 3D object space in a fast and efficient way took a while to wrap my head around, but finally, with quite a bit of help from my math guru of a wife I have a nice and efficient "translateLocal" method in Renderer:

def translateLocal(x: Double, y: Double, m: Matrix4, store: MutableVector3) = {
  synchronized {
   storeRay.origin.set(0.0, 0.0, 0.0)
   storeRay.direction.set(x, y, -nearDistance)
   
   storeMatrix.set(m)
   storeMatrix.invert()
   storeRay.transform(storeMatrix)
   storeRay.translateLocal(store)
   
   store
  }
 }

Today I'm working on integration of this within the Component architecture to support determination of hits within bounding regions. This does not create any additional garbage and I can run this on my machine about a million times in 700ms. Ideally I'd like the performance to be better than that, but since this does not absolutely have to be done within the rendering thread and with optimizations to limit the checks in the first place the performance should be fine.

Upgrading to LWJGL 2.4.2 from 2.2.2 gave me a framerate improvement of about 40% in my examples which is nice. :)

Next steps are to finish bounding support for BoundingQuad (what all my 2D UI components will use) and then start working on Scale-9 images, Label, TextInput, and multi-line text support with selection ability along with focus management.

Sunday, April 11, 2010

ImageCube

It's been a few days since my last post, but I've been endeavoring to make strides toward fully 3D UI concepts and it hasn't been altogether easy to do. It is relatively straight-forward to create a 2D UI and it's even relatively easy to create a 3D game, but developing a powerful and easy-to-use engine that provides both full 3D and advanced user-interface development functionality is a more complicated road to take.

The following video shows my ImageCube leveraging 3D, adjustable properties, easings, and my new effects framework. This is all still very early development, but as you can see the "effects" essentially make up a work-flow of actions to take in sequence. At the moment I've got:
  • CompositeEffect - executes multiple effects in sequence
  • PauseEffect - creates a delay
  • PropertyChangeEffect - will apply a value to a property upon invocation, primarily designed to work with AdjustableProperties
  • PropertySetEffect - immediately applies a value to the property ignoring any existing adjusters



Here's the code:
package org.sgine.ui

import org.sgine.core.Resource

import org.sgine.easing.Elastic
import org.sgine.easing.Linear

import org.sgine.effect.CompositeEffect
import org.sgine.effect.PropertyChangeEffect
import org.sgine.effect.PropertySetEffect

import org.sgine.math.mutable.MatrixPropertyContainer

import org.sgine.property.adjust.EasingNumericAdjuster

import org.sgine.render.Renderer
import org.sgine.render.scene.RenderableScene

import org.sgine.scene.GeneralNodeContainer

object TestCube {
 def main(args: Array[String]): Unit = {
  val r = Renderer.createFrame(1024, 768, "Test Cube", 4, 8, 4, 4)
  r.verticalSync := false
  
  val scene = new GeneralNodeContainer()
  
  val cube = new ImageCube()
  cube.location.z := -1500.0
  cube.rotation.x.adjuster = new EasingNumericAdjuster(Linear.easeIn, 2.0)
  cube.rotation.y.adjuster = new EasingNumericAdjuster(Linear.easeIn, 4.0)
  cube.rotation.z.adjuster = new EasingNumericAdjuster(Linear.easeIn, 6.0)
  cube.location.x.adjuster = new EasingNumericAdjuster(Elastic.easeInOut, 4.0)
  cube(Resource("resource/sgine_256.png"), 256.0, 256.0)
  scene += cube
  
  r.renderable := RenderableScene(scene, showFPS = true)
  
  // Rotate the cube perpetually on the x-axis
  val rx1 = new PropertyChangeEffect(cube.rotation.x, Math.Pi * 2.0)
  val rx2 = new PropertySetEffect(cube.rotation.x, 0.0)
  val rotateX = new CompositeEffect(rx1, rx2)
  rotateX.repeat = -1
  
  // Rotate the cube perpetually on the y-axis
  val ry1 = new PropertyChangeEffect(cube.rotation.y, Math.Pi * 2.0)
  val ry2 = new PropertySetEffect(cube.rotation.y, 0.0)
  val rotateY = new CompositeEffect(ry1, ry2)
  rotateY.repeat = -1
  
  // Rotate the cube perpetually on the z-axis
  val rz1 = new PropertyChangeEffect(cube.rotation.z, Math.Pi * 2.0)
  val rz2 = new PropertySetEffect(cube.rotation.z, 0.0)
  val rotateZ = new CompositeEffect(rz1, rz2)
  rotateZ.repeat = -1
  
  // Move the cube back and forth perpetually on the x-axis
  val me1 = new PropertyChangeEffect(cube.location.x, -600.0)
  val me2 = new PropertyChangeEffect(cube.location.x, 600.0)
  val move = new CompositeEffect(me1, me2)
  move.repeat = -1
  
  // Start effects
  rotateX.start()
  rotateY.start()
  rotateZ.start()
  move.start()
 }
}

Wednesday, April 7, 2010

eSCALAtion Blog Interview

I was asked to give a brief interview with the Scala blog "eSCALAtion" regarding sgine. Here is the link: http://dgronau.wordpress.com/2010/04/05/interview-with-matt-hicks/

Monday, April 5, 2010

Beginnings of Components

Last week I made a new post daily outlining the work of the day, showing a screenshot of the progress, and posting a code sample. This past weekend I didn't post anything, but not because I wasn't working hard, but because primarily what I was working on had no real visual presence. A quick look at the change log for Mercurial will show significant increase in code being checked in: see!

Last week I showed how nicely both images and text can be displayed to the screen with relatively little amounts of code, but that code is not very practical from a modularity and simplicity perspective. The goal was never for developers to rely specifically on that functionality but to work as a core to build upon within sgine to provide more powerful abstractions for developers to use in order to develop with simplicity and logically.

This past weekend I spent quite a bit of time working on what I consider to be the fulfillment of that objective (or at least the beginning of) through the use of what I call Components. Components in sgine are sort of a hybrid between what would classically be a Node/Spatial in a 3D scenegraph and a Component / Widget in a standard GUI like Swing. There will be much more coming soon on this topic, but for now I'll leave you with a very short snippet to portray the same as my original example did of the puppies but using the Image component in sgine:

package org.sgine.ui

import org.sgine.core.Resource

import org.sgine.easing.Elastic

import org.sgine.property.adjust.EasingNumericAdjuster

import org.sgine.render.Renderer
import org.sgine.render.scene.RenderableScene

import org.sgine.scene.GeneralNodeContainer

object TestImage {
 def main(args: Array[String]): Unit = {
  val r = Renderer.createFrame(1024, 768, "Test RenderScene")
  
  val scene = new GeneralNodeContainer()
  val component = new Image()
  component.location.z := -1000.0
  component.source := Resource("resource/puppies.jpg")
  scene += component
  
  r.renderable := RenderableScene(scene)
 }
}

Friday, April 2, 2010

Font Testing

I think I'm just about done with the first pass on bitmap font work. I still need to provide convenience methods for determining size of blocks of text and paragraph support as well as creating a system to dynamically generate bitmapped fonts via AWT at runtime, but I think I've finally knocked out all the major bugs. Here is a prettier example using the AngelCode fonts I've been working on:



Finally starting to look like something useful and less like a crappy hobby project, but still a long way to go. Anyway, here's the source:

package org.sgine.render

import org.sgine.math.mutable.Matrix4

import javax.imageio.ImageIO

import org.lwjgl.opengl.GL11._

import scala.io.Source

object TestFonts {
 def main(args: Array[String]): Unit = {
  val r = Renderer.createFrame(1024, 768, "Test Fonts")

  val franklinFont = AngelCodeFont(Source.fromURL(getClass.getClassLoader.getResource("resource/Franklin.fnt")), getClass.getClassLoader.getResource("resource/Franklin.png"))
  val arialFont = AngelCodeFont(Source.fromURL(getClass.getClassLoader.getResource("resource/Arial.fnt")), getClass.getClassLoader.getResource("resource/Arial.png"))
  val lcdFont = AngelCodeFont(Source.fromURL(getClass.getClassLoader.getResource("resource/lcd.fnt")), getClass.getClassLoader.getResource("resource/lcd.png"))
  
  val m1 = Matrix4().translate(x = -400.0, z = -1000.0)
  val m2 = Matrix4().translate(x = -100.0, y = -50.0, z = -1000.0)
  val fps = FPS(1.0, lcdFont)
  
  val a = new Array[() => Unit](5)
  a(0) = MatrixState(m1)
  a(1) = () => franklinFont.drawString("Franklin Gothic Heavy with a blue gradient.", true)
  a(2) = MatrixState(m2)
  a(3) = () => arialFont.drawString("Standard Arial", false)
  a(4) = fps
  r.renderable := RenderList(a)
 }
}

AngelCode Fonts - Kerning

I already did most of the legwork earlier this week, but hadn't gotten around to turning on support for kerning, but that's all changed now:



Pretty easy to see the benefits of kerning here. However, this example also shows I seem to have a little problem with my low-hanging characters like 'g' and 'p'. Hopefully that will be fixed in the next update.

For now, here's the source:

package org.sgine.render

import org.sgine.math.mutable.Matrix4

import javax.imageio.ImageIO

import org.lwjgl.opengl.GL11._

import scala.io.Source

object TestFonts {
 def main(args: Array[String]): Unit = {
  val r = Renderer.createFrame(1024, 768, "Test Fonts")
  
  val m1 = Matrix4().translate(x = -200.0, z = -1000.0)
  val m2 = Matrix4().translate(x = -200.0, y = -25.0, z = -1000.0)
  val fps = FPS(1.0)
  
  val font = AngelCodeFont(Source.fromURL(getClass.getClassLoader.getResource("resource/Arial.fnt")), getClass.getClassLoader.getResource("resource/Arial.png"))
  
  val a = new Array[() => Unit](5)
  a(0) = MatrixState(m1)
  a(1) = () => font.drawString("VAST Kerning Example Enabled", true)
  a(2) = MatrixState(m2)
  a(3) = () => font.drawString("VAST Kerning Example Disabled", false)
  a(4) = fps
  r.renderable := RenderList(a)
 }
}

A couple more days of effort and we can hopefully dig into some much more interesting features. :)

Wednesday, March 31, 2010

AngelCode Fonts - Second Steps

I was determined to get some more work done on this today after my sorry screenshot I posted last night. I've added parsing support to kerning but have not implemented it graphically. Hopefully I'll get around to that tomorrow. However, the xOffset, yOffset, and xAdvance functionality is working now and I have a much better screenshot to post:



I've also cleaned up the process by adding a "drawString" method to AngelCodeFont. See the following example code:

package org.sgine.render

import org.sgine.math.mutable.Matrix4

import javax.imageio.ImageIO

import org.lwjgl.opengl.GL11._

import scala.io.Source

object TestFonts {
 def main(args: Array[String]): Unit = {
  val r = Renderer.createFrame(1024, 768, "Test Fonts")
  
  val m = Matrix4().translate(x = -70.0, z = -1000.0)
  val fps = FPS(1.0)
  
  val font = AngelCodeFont(Source.fromURL(getClass.getClassLoader.getResource("resource/Arial.fnt")), getClass.getClassLoader.getResource("resource/Arial.png"))
  
  val a = new Array[() => Unit](3)
  a(0) = MatrixState(m)
  a(1) = () => font.drawString("Hello World!")
  a(2) = fps
  r.renderable := RenderList(a)
 }
}

Tuesday, March 30, 2010

AngelCode Fonts - First Steps

I spent a little bit of time the past couple of evenings writing a parser in Scala to process AngelCode font files so sgine could support bitmap fonts and though the actual results look a bit sad, the progress is quite nice. :)

Now, I know this looks ugly, but for a combined time of less than two hours I think it's some decent progress:



You'll notice the x and y offsets are not specified, and I sort of hard-coded multi-character rendering, but still, it's a start. :)

Here's the code required:
package org.sgine.render

import org.sgine.math.mutable.Matrix4

import javax.imageio._

import org.lwjgl.opengl.GL11._

import scala.io.Source

object TestFonts {
 def main(args: Array[String]): Unit = {
  val r = Renderer.createFrame(1024, 768, "Test Fonts")
  
  val m = Matrix4().translate(z = -1000.0)
  val fps = FPS(1.0)
  
  val font = AngelCodeFont(Source.fromURL(getClass.getClassLoader.getResource("resource/Arial.fnt")), getClass.getClassLoader.getResource("resource/Arial.png"))
  
  val a = new Array[() => Unit](13)
  a(0) = MatrixState(m)
  a(1) = () => font('H').draw(-60.0)
  a(2) = () => font('e').draw(-40.0)
  a(3) = () => font('l').draw(-20.0)
  a(4) = () => font('l').draw(0.0)
  a(5) = () => font('o').draw(20.0)
  a(6) = () => font(' ').draw(40.0)
  a(7) = () => font('W').draw(60.0)
  a(8) = () => font('o').draw(80.0)
  a(9) = () => font('r').draw(100.0)
  a(10) = () => font('l').draw(120.0)
  a(11) = () => font('d').draw(140.0)
  a(12) = fps
  r.renderable := RenderList(a)
  
  println("Renderer started! " + 81.asInstanceOf[Char] + " - " + font.face + ", " + font.size)
 }
}

Next step is to properly support drawing of Strings correctly. More to come soon.

Sunday, March 28, 2010

Replacement Renderer

Not really a lot to see at the moment. The engine has been taken apart and put back together a few times, but finally I think we're going to start making some serious progress. To that end I'm planning on documenting here as things progress.

I've just recently completely started over with renderer in sgine and am getting pretty nice framerates even if I am just rendering an image of my two puppies:



Over the next few weeks the UI framework will be coming together hopefully along with much of the functionality I had previously written in to jSeamless.

Here's the code required:

package org.sgine.render

import org.sgine.math.Matrix4

import javax.imageio._

import org.lwjgl.opengl.GL11._

object TestRenderer {
 def main(args: Array[String]): Unit = {
  val r = Renderer.createFrame(1024, 768, "Test Renderer")
  
  val t = new Texture(700, 366)
  TextureUtil(t, ImageIO.read(getClass.getClassLoader.getResource("resource/puppies.jpg")), 0, 0, 700, 366)
  
  val m = Matrix4().translate(z = -1000.0)
  val i = Image(t)
  val fps = FPS(1.0)
  
  r.renderable := RenderList(MatrixState(m) :: i :: fps :: Nil)
  
  println("Renderer started!")
 }
}

Stay tuned.
Scala Engine for high-performance interactive applications.