Game: World Editor Beginnings

In this post, I’ll document some of the blow-by-blow of a (hopefully!) rapid bring up of a world editor. Rapid means different things to different people… I’m hoping for a couple of weeks here.

Wednesday, 2015-03-25

Haven’t looked at the codebase in about a week and half, was busy getting ready for the first deployment of my Video Feedback Toy at a private event at Chabot Science Center. Went well. Is built on MeLib just like Metareal will be.

Spent day at Cafe Pergolesi and the downtown Santa Cruz Public Library, created fresh project, and added some MeLib features for specifying viewport and scissoring for each MeRenderworld step. End of day:

MeEd01

A content area, & an info area. Pretty special!

Thursday, 2015-03-26

Tragically, the current state of my libraries is still that bringing stuff up has a painful-feeling up-front cost. Spent a couple of hours bringing forward some text console code, and managing an array of items. The process of bringing up this editor will imply creating the World Model, too. Gets and sets, here we come!

But for now, just a shallow visual presence.

MeEd02 MeEd02

 

Friday, 2015-03-27

Short workday today. Worked on some serialization. I have a “parameterizable thing manager”, which can instantiate subclasses of MeThing by class name. Today, brought in some XML code from another project to easily save the complete state of some things to a file.

There are smart people who seem to hate XML, but I think it’s just fine.

Anyway, the code to render to XML is quite easy (if you have enough good stuff behind it):

    std::string toXml()
    {
        StringXmlWriter *sx = new StringXmlWriter();
        OmXmlWriter *w = new OmXmlWriter(sx);
        w->beginElement("level");
        for(auto thing : this->things)
        {
            MeThingKind *kind = thing->getKind();
            w->beginElement("thing");
            w->addAttribute("kind", kind->getName().c_str());
            w->addAttribute("name", thing->getName().c_str());
            for(auto pd : kind->getParameterDescriptions())
            {
                w->beginElement("parameter");
                w->addAttribute("name", pd.name.c_str());
                w->addAttribute("value", thing->getValueString(pd.name).c_str());
                w->endElement();
            }
            w->endElement();
        }
        
        w->endElement();
        
        std::string result = sx->s;
        
        delete w;
        delete sx;
        
        return result;
    }

And produces a nice little text:

 <level>
  <thing kind="Thing1" name="">
   <parameter name="x" value="1e+20"/>
   <parameter name="y" value="0"/>
   <parameter name="i" value="0"/>
   <parameter name="color" value="1 , 0 , 0.5 , 1"/>
  </thing>
  <thing kind="Thing2" name="item 1">
   <parameter name="x" value="111.11"/>
   <parameter name="y" value="0"/>
   <parameter name="j" value="0"/>
  </thing>
  <thing kind="Thing1" name="item 2">
   <parameter name="x" value="-1e-20"/>
   <parameter name="y" value="0"/>
   <parameter name="i" value="0"/>
   <parameter name="color" value="1 , 0 , 0.5 , 1"/>
  </thing>
  <thing kind="Thing1" name="item 3">
   <parameter name="x" value="0"/>
   <parameter name="y" value="0"/>
   <parameter name="i" value="0"/>
   <parameter name="color" value="23 , 42 , 86 , 99"/>
  </thing>
 </level>

Saturday, 2015-03-28

They don’t work for money any more, or to earn a place in heaven (which was a big motivating factor once upon a time, believe you me). They’re working and inventing because they like it. Linda, Larry, there’s no concept of weekends any more! — Spaulding Grey in True Stories

This “no corporate employment” changes how time works. On the other hand, weekends are when my friends are around, so spent a few hours today helping one move. I always take the Truck Arranger role, for best stacking.

Implemented a first pass at XML loading for the editor. I have a c++ class built around expat2, so you can receive individual elements on two callbacks, like so:

    void beginElement(std::string elementName, std::map<std::string, std::string> &attributes)
    {
        if(elementName == "thing")
        {
            std::string thingKind = attributes["kind"];
            std::string thingName = attributes["name"];
            MeThing *thing = this->tm->newInstance(thingKind);
            thing->setName(thingName);
            this->things.push_back(thing);
            this->xmlCurrentThing = thing;
        }
        else if(elementName == "parameter")
        {
            if(this->xmlCurrentThing)
            {
                std::string name = attributes["name"];
                std::string value = attributes["value"];
                this->xmlCurrentThing->setValueString(name, value);
            }
        }
    }
    void endElement(S elementName)
    {
        std::string e = elementName;
        if(e == "thing")
            this->xmlCurrentThing = NULL;
    }

Two points of magic to note. As alluded to earlier, this->tm is a MeThingManager. It has the ability to instantiate different implementations of MeThing by name. The other is thing->setValueString(), which does a best-effort interpretation of text for the particular type of the named parameter.

So far, these thing-lists are just abstract bags of parameters. Next up, defining some thing kinds with a geometrical, visual presence. Probably cubes.

Sunday, 2015-03-29

Development shortcut: All UI is performed with the existing keyboard space navigation (6-axis fly-around using esdf/ijkl), and a text console.

Library has only one kind of Object in it, a cube. The cube only has position. Can be added & moved around, and saved & restored to XML. Can tab to edit different Objects, and page up/down keys to select different parameters to edit.

MeEd03

 

It’s inscrutable if you’re not me (but I am, so that’s ok for now), and it’s just barely enough.

Next up, managing rooms & walls, as well; these may be handled differently than the live objects.

Next up after that, letting the level “run”.

Tuesday, 2015-03-31

Life of a full-stack developer. To implement mouse hit-testing, needed to add an alternate shader that operates on the same geometry. To keep the shaders in sync, had to implement #include for the shader file loader. So had to flesh out my OmFile:: utility file library. (With benefit of well-defined swap point for platform porting.)

editorHitTest

Tuesday, 2015-04-07

And I think I’ll wrap up this post now. In the last week, many low-glamor changes such as keyboard bindings for numeric editing individual params, snapping to multiples, and the like. Mouse click selection throughout. A Material Manager class, so instantiated objects can reference their required shaders by name.

End result: can instantiate several different types of objects, edit & delete them, save & recall to disk.

2015-04-07

Onwards! A long slow path.

Leave a Reply

Your email address will not be published.