The Spatials V3 devblog 2015-10-12

Internal development notes, very slightly cleaned up and commented a week later.

TL;DR: In the past week more experiments in search for a selection cursor UI were done, a job matrix UI for officers was implemented, the state machine library received more fixes, job logistics now support multiple resources and are intelligent about asking for workers only when needed, and the keyboard support was improved.

- DisplaySystem::
    utility draw functions with direct Scheme binding for very basic vector graphics
    cocos2d::CCNode* isoCircumference(float r, float stroke, std::string color, float alpha);
    cocos2d::CCNode* isoCircle(float r, std::string color, float alpha);
    cocos2d::CCNode* isoRectLines(float w, float h, float stroke, std::string color, float alpha);
    cocos2d::CCNode* isoRect(float w, float h, std::string color, float alpha);
    cocos2d::CCNode* isoLine(float x2, float y2, float stroke, std::string color, float alpha);
    cocos2d::CCNode* isoVerticalLine(float sh, float stroke, std::string color, float alpha);
 - debug info tool: use vector drawing to display PositionComponent::boundary of selected entity

Some iso-projected vector drawing methods were implemented. Their signature is choosen as to be automatically exposed to Scheme by the binding preprocessor. They were put to work in the debug tool. This selection display is still too poor and needs more work. The V2 solution (screen-aligned rect) used hardcoded values for the sizing of sprites, a notion that doesn’t exists in V3 and which I am trying to avoid.

- more info cursor
	on click, a determinist sorted list of all the entitites in the cursor boundary is built
		use distance to cursor
	if one of them is already selected, the next one is selected (with wrap around)
	if none, select the first

The debug info tool is now capable of selecting overlapping entities in a more sensible way. Just click again in the same spot to select the next entity. This mechanic is ready for the final info tool.

- tool shell: support down panel
- buttons: handle discarding clicks while being inside a scroll view and cliped out
	walk parents and stop to check those that give trouble (scrollview)
	getViewRect is already doing all the work, use it
- model: job metadata to enable job matrix
- job matrix tool
	handle staff changes
		redraw using gui-observer
	handle toggling
		add and change model
		redraw using gui-observer
		change world entities to reflect model
- bug: proto job matrix panel scroller doesnt get scrollwheel events, sidebars do
	was using the wrong coords transform, sidebars "worked" because of being screen-tall (blind spot at bottom gave hint)

A staple of management sims is now implemented: a job matrix. It’s automatically built from metatdata exported by the various job systems. Any job system can expose a component that workers can look for when interested in the job, plus associated data like the its name. There’s also data for building the job listing using priorities, but it’s not yet implemented.

- very scary: ecs-has-component? not found in stock.scm, but only after loading game
	sm state is serialized as inlet, which makes it lose its env
	after load, sm then is run with the state in its parent chain, whose parent (rootlet) doesnt have ecs.scm inside
	fix: just (set! (outlet state) (curlet)) on sm run

A very puzzling bug was found in the state machine library, which after serialization (save/load) was missing the proper Scheme environment for being run. After some experimentation the cause was obvious. The serialized representation of an inlet (the first-class environment object in S7 Scheme) sheds the reference to its parent, and after deserializing it, it points to the rootlet. V3 never uses the rootlet and instead has a second level private environment (S7 cannot be deinitialized, so this is needed to support new/load game). Since the state machine runner executes its logic inside a sublet of the state machine inlet, and it also expects the full game library to be available thru this inlet. Having the rootlet as a parent, this wasn’t true. The problem was fixed by making sure the parent of the state machine inlet being the lexical environment of the state machine runner.

- more work on jobs: multi resource, avoid busy-ing worker spam
	problem: jobs with resource gather: always available for workers, even when no stocks can be fetched
	multi-resource jobs are a mess to implement right now
	tackle both issues with a reworked sm + helpers for clarity
		job sm controls publishing of the job component, only does when appears to be available stock
			job component is only added when at least one of the resources is available
			it is removed in cleanup state
			delivered resources are destroyed and the sm goes back to waiting for them
			job info comp keeps track of the delivered resources
		the job logistic component keeps count of delivered resources/amounts
		only when matching desired amounts, the actual job is advertised
- making the job invalid while still gathering makes it forget the gathered resources
	clear gathered resources only after completion, do not clear in cleanup
- remove job-logistic-info-component and use another attrib in the state component
	otherwise multijobs-per-entity will be impossible
- port exisiting users of job sm to the new one

Another week, another pass over the job-logistic state machine. This time it gained support for fetching multiple resources. The key to make this simple was to destroy the resource entities after delivery. This frees the SM from having to keep track of all the individual delivered entities. The SM was also made smarter about not requesting workers while it detects that there are no available resources.

job-logistic-info-component also disapeared, and its data was added to the user-suplied state component. This will allow to run multiple instances of the same state machine over a single entity.

- job logistic sm: directly consume from available stacks in the 9-neigh when possible, before sending the worker to fetch them
- proto production system: cooking
	a plain logistic job with a single ingredient, using the new mechanics

A kitchen was implemented to prototype a new idea in the logistic SM. Having to fetch resources for every task can make production slow. The pallet system allows to keep important resources near the places that need them, but they still require a worker to walk and fetch them. In order to make the resource fetch go faster the job-logistic SM is now able to directly consume resources from pallets in the immediate area of a job entity (this is the 8 neighboring tiles).

In this video it can be seen in action. The two flanking pallets are set to restock the Seeds resource, while the kitchen in the middle is constantly producing Pizzas, which require 3 Seeds.

It’s interesting to see the new state / transition diagram for the job-logistic SM and compare it to the previous week diagram:

Notice the new transition to allow for multi-resource (deliver-item to wait-for-resources when held, because that means a delivery was done, so there maybe more waiting), how wait-for-worker is only activated when any-item has been found or when no resource is required, and the new wait-for-resources-anywhere state, which loops with the original wait-for-resources in order to enable both nearby pallet consumption and gathering of remote resources.

- add capturing to keyboard handler
- use scrolling list for key binding screen (GUIListing)
- allow to unbind keys in options screen
- re-enable keyboard movement/zoom in station
- add priorities to keyboard handler
- generic esc/enter support for MessageAlert, including esc = X button for alerts with no label buttons

Keyboard event handling was finally made first class, with the introduction of priorities and handlers now being able to request exclusivity for events. The keyboard Options screen is now based on a proper list and modal popups support Enter and Escape accept/dismissal. WASD was also restored for scrolling in the station.