Remove Atlas UI scripting support

This was SVN commit r9567.
This commit is contained in:
Ykkrosh 2011-05-29 15:43:08 +00:00
parent dc2035efc9
commit a81f180dd6
13 changed files with 0 additions and 1945 deletions

View File

@ -1,139 +0,0 @@
//////////////////////////////////////////////////////////////////////////////
// Terrain preview page
//
// Used by new dialog and terrain panel
global.TerrainPreviewPage = function(panel, name, width, height)
{
this.panel = panel;
this.name = name;
// Size of texture preview images
this.w = width ? width : 120
this.h = height ? height : 40;
this.lastTerrainSelection = null; // button that was last selected, so we can undo its colouring
this.previewReloadTimer = null;
}
global.TerrainPreviewPage.prototype = {
reloadPreviews: function()
{
this.panel.freeze();
this.scrolled.destroyChildren();
this.itemSizer.clear();
this.lastTerrainSelection = null; // clear any reference to deleted window
var previews = Atlas.Message.GetTerrainGroupPreviews(this.name, this.w, this.h).previews;
var i = 0;
var names = [];
var allLoaded = true;
for each (var p in previews)
{
if (!p.loaded)
{
allLoaded = false;
}
// Create a wrapped-text label (replacing '_' with ' ' so there are more wrapping opportunities)
var labelText = p.name.replace(/_/g, ' ');
var label = new wxStaticText(this.scrolled, -1, labelText, wxDefaultPosition, wxDefaultSize, wxStaticText.ALIGN_CENTER);
label.wrap(this.w);
var imgSizer = new wxBoxSizer(wxOrientation.VERTICAL);
var button = new wxBitmapButton(this.scrolled, -1, p.imagedata);
var self = this;
button.terrainName = p.name;
button.onClicked = function()
{
Atlas.SetSelectedTexture(this.terrainName);
if (self.lastTerrainSelection)
{
self.lastTerrainSelection.backgroundColour = wxNullColour;
}
this.backgroundColour = new wxColour(255, 255, 0);
self.lastTerrainSelection = this;
};
imgSizer.add(button, 0, wxAlignment.CENTRE);
imgSizer.add(label, 1, wxAlignment.CENTRE);
this.itemSizer.add(imgSizer, 0, wxAlignment.CENTRE | wxStretch.EXPAND);
}
this.itemSizer.layout();
this.panel.layout();
this.panel.thaw();
// If not all textures were loaded yet, run a timer to reload the previews
// every so often until they've all finished
if (allLoaded && this.previewReloadTimer)
{
this.previewReloadTimer.stop();
this.previewReloadTimer = null;
}
else if (!allLoaded && !this.previewReloadTimer)
{
this.previewReloadTimer = new wxTimer();
var self = this;
this.previewReloadTimer.onNotify = function() { self.reloadPreviews(); };
this.previewReloadTimer.start(2000);
}
},
display: function()
{
if (this.loaded)
{
return;
}
this.panel.sizer = new wxBoxSizer(wxOrientation.VERTICAL);
var scrolled = new wxScrolledWindow(this.panel, -1, wxDefaultPosition, wxDefaultSize, wxWindow.VSCROLL);
scrolled.setScrollRate(0, 10);
scrolled.backgroundColour = new wxColour(255, 255, 255);
this.panel.sizer.add(scrolled, 1, wxStretch.EXPAND);
var itemSizer = new wxGridSizer(6, 4, 0);
scrolled.sizer = itemSizer;
// Adjust the number of columns to fit in the available area
var w = this.w;
scrolled.onSize = function (evt)
{
var numCols = Math.max(1, Math.floor(evt.size.width / (w+16)));
if (itemSizer.cols != numCols)
{
itemSizer.cols = numCols;
}
};
this.scrolled = scrolled;
this.itemSizer = itemSizer;
this.reloadPreviews();
// TODO: fix keyboard navigation of the terrain previews
this.loaded = true;
}
};
global.TerrainPreviewNotebook = function(window)
{
var terrainGroups = Atlas.Message.GetTerrainGroups();
var nb = new wxNotebook(window, -1);
window.sizer = new wxBoxSizer(wxOrientation.VERTICAL);
window.sizer.add(nb, 1, wxStretch.EXPAND);
var pages = [];
nb.onPageChanged = function (evt)
{
pages[evt.selection].display()
evt.skip = true;
}
for each (var groupName in terrainGroups.groupNames)
{
var panel = new wxPanel(nb, -1);
var page = new global.TerrainPreviewPage(panel, groupName);
pages.push(page);
nb.addPage(panel, groupName); // TODO: use Titlecase letters
}
}

View File

@ -1,123 +0,0 @@
Atlas.RenderView = {
GAME: 1,
ACTOR: 2
}; // TODO: this should probably be defined by the C++ code
// Define the default state settings.
// (It's done this way so that this script can be dynamically reloaded,
// and won't overwrite the previous runtime state but will still pick
// up any new properties)
var defaults = {
objectSettings: {
view: Atlas.RenderView.GAME,
selectedObjects: [],
playerID: 1,
actorSelections: [],
variantgroups: []
}
};
defaults.objectSettings.toSObjectSettings = function () {
return {
player: this.playerID,
selections: this.actorSelections
};
}
defaults.objectSettings.onSelectionChange = function () {
if (! this.selectedObjects.length) {
// TODO: do something sensible here
this.actorSelections = [];
this.variantgroups = [];
} else {
// TODO: Support multiple selections
var selection = this.selectedObjects[0];
var settings = Atlas.Message.GetObjectSettings(this.view, selection).settings;
if (settings.player != -1)
this.playerID = settings.player;
this.actorSelections = settings.selections;
this.variantgroups = settings.variantgroups;
}
this.notifyObservers();
}
/**
* Returns the current actor variation (as a list of chosen variants), based
* on its variant groups and the selection strings. This is equivalent to the
* variation rendered by the game.
*/
defaults.objectSettings.getActorVariation = function ()
{
var selectionMap = {};
for each (var s in this.actorSelections)
selectionMap[s] = 1;
var variation = [];
GROUP: for each (var group in this.variantgroups) {
for each (var variant in group) {
if (variant in selectionMap) {
variation.push(variant);
continue GROUP;
}
}
// None selected; default to first
variation.push(group[0]);
}
return variation;
}
// Merges the 'defs' tree into 'obj', overwriting any old values with
// the same keys
function setDefaults(defs, obj)
{
for (var k in defs) {
if (k in obj)
setDefaults(defs[k], obj[k]);
else
obj[k] = defaults[k];
}
}
function makeObservable(obj)
{
// If the object has already been set up as observable, don't do any more work.
// (In particular, don't delete any old observers, so they don't get lost when
// this script is reloaded.)
if (typeof obj._observers != 'undefined')
return;
obj._observers = [];
obj.registerObserver = function (callback) {
this._observers.push(callback);
}
obj.unregisterObserver = function (callback) {
this._observers = this._observers.filter(function (o) { return o !== callback });
}
obj.notifyObservers = function () {
for each (var o in this._observers)
o(this);
};
}
function postObjectSettingsToGame(objectSettings)
{
// TODO: if view != GAME, we don't really want this to be an undoable command
if (objectSettings.selectedObjects.length)
Atlas.Message.SetObjectSettings(objectSettings.view,
objectSettings.selectedObjects[0], objectSettings.toSObjectSettings());
}
function init()
{
setDefaults(defaults, Atlas.State);
makeObservable(Atlas.State.objectSettings);
Atlas.State.objectSettings.registerObserver(postObjectSettingsToGame);
}
function deinit() {
Atlas.State.objectSettings.unregisterObserver(postObjectSettingsToGame);
}

View File

@ -1,139 +0,0 @@
function getScriptFilename(name)
{
var relativePath = 'tools/atlas/scripts/' + name + '.js';
var filename = new wxFileName(relativePath, wxPathFormat.UNIX);
filename.normalize(wxPathNormalize.DOTS | wxPathNormalize.ABSOLUTE | wxPathNormalize.TILDE,
Atlas.GetDataDirectory()); // equivalent to MakeAbsolute(dir);
return filename;
}
/**
* Loads and executes a script from disk. The script runs in a separate scope,
* so variables and functions declared in it will not be visible outside that file.
*/
function loadScript(name /*, ...*/)
{
var filename = getScriptFilename(name);
var file = new wxFFile(filename.fullPath);
var script = file.readAll(); // TODO: handle errors
file.close();
var script = Atlas.LoadScript(name+'.js', script);
// Extract the arguments which the function will actually use
// (Can't use Array.slice since arguments isn't an Array)
// (Have to do this rather than use arguments.length, since we sometimes
// pass unused bottomWindows into init and then destroy the window when realising
// it wasn't used, and then we mustn't send the destroyed window again later)
var args = [];
if (script.init)
for (var i = 1; i < 1+script.init.length; ++i)
args.push(arguments[i]);
scriptReloader.add(name, args, filename, script);
if (script.init)
script.init.apply(null, args);
return script;
}
/**
* Helper function for C++ to easily set dot-separated names
*/
function setValue(name, value)
{
var obj = global;
var props = name.split(".");
for (var i = 0; i < props.length-1; ++i)
obj = obj[props[i]];
obj[props[props.length-1]] = value;
}
/**
* Helper function for C++ to easily get dot-separated names
*/
function getValue(name)
{
var obj = global;
var props = name.split(".");
for (var i = 0; i < props.length; ++i)
obj = obj[props[i]];
return obj;
}
function loadXML(name)
{
var relativePath = 'tools/atlas/' + name + '.xml';
var filename = new wxFileName(relativePath, wxPathFormat.UNIX);
filename.normalize(wxPathNormalize.DOTS | wxPathNormalize.ABSOLUTE | wxPathNormalize.TILDE,
Atlas.GetDataDirectory()); // equivalent to MakeAbsolute(dir);
var file = new wxFFile(filename.fullPath);
var xml = file.readAll(); // TODO: handle errors
// TODO: complain (or work) nicely if the XML file starts with
// "<?xml ...?>" (which E4X doesn't like parsing)
file.close();
return new XML(xml);
}
// Automatically reload scripts from disk when they have been modified
var scriptReloader = {
timer: new wxTimer(),
scripts: [], // [ {name, args, filename, mtime, window, script}, ... ]
notify: function ()
{
for each (var script in scriptReloader.scripts)
{
var mtime = script.filename.modificationTime;
if (mtime - script.mtime != 0)
{
print('*** Modifications detected - reloading "' + script.name + '"...\n');
script.mtime = mtime;
if (script.script && script.script.deinit)
script.script.deinit();
if (script.name == 'main')
{
// Special case for this file to reload itself
script.script = loadScript(script.name, null);
// Copy the important state into the new version of this file
script.script.scriptReloader.scripts = scriptReloader.scripts;
// Stop this one
scriptReloader.timer.stop();
}
else
{
// TODO: know which arguments are really windows that should be regenerated
for each (var window in script.args)
window.destroyChildren();
script.script = loadScript.apply(null, [script.name].concat(script.args));
for each (var window in script.args)
window.layout();
}
}
}
},
add: function (name, args, filename, script)
{
for each (var s in this.scripts)
if (s.name == name)
return; // stop if this is already loaded
this.scripts.push({ name:name, args:args, filename:filename, mtime:filename.modificationTime, script:script });
}
};
scriptReloader.timer.onNotify = scriptReloader.notify;
scriptReloader.timer.start(1000);
scriptReloader.add('main', null, getScriptFilename('main'));
loadScript('editorstate');
// Export global functions:
global.loadScript = loadScript;
global.loadXML = loadXML;
global.setValue = setValue;
global.getValue = getValue;

View File

@ -1,552 +0,0 @@
function setupSimTest(window, rmsPanel)
{
var state = 'inactive'; // inactive, playing
var speed = 0;
function play(newSpeed)
{
if (state == 'inactive')
{
Atlas.Message.SimStateSave('default');
Atlas.Message.GuiSwitchPage('page_session.xml');
}
Atlas.Message.SimPlay(newSpeed);
state = 'playing';
speed = newSpeed;
updateEnableStatus();
}
function reset()
{
if (state == 'playing')
{
Atlas.Message.SimStateRestore('default');
Atlas.Message.GuiSwitchPage('page_atlas.xml');
}
Atlas.Message.SimPlay(0);
state = 'inactive';
speed = 0;
updateEnableStatus();
}
function updateEnableStatus()
{
for (var i in buttons)
{
buttons[i][3].enable = buttons[i][2]();
}
if (state == 'playing')
{
// Disable RMS controls
rmsPanel.enable = false;
}
else
{
rmsPanel.enable = true;
}
}
var speeds = [ 1/8, 1, 8 ];
var buttons = [
/* button label; click command; active condition */
[ 'Play', function () { play(speeds[1]) }, function () { return !(state == 'playing' && speed == speeds[1]) } ],
[ 'Fast', function () { play(speeds[2]) }, function () { return !(state == 'playing' && speed == speeds[2]) } ],
[ 'Slow', function () { play(speeds[0]) }, function () { return !(state == 'playing' && speed == speeds[0]) } ],
[ 'Pause', function () { play(0) }, function () { return state == 'playing' && speed != 0 } ],
[ 'Reset', function () { reset() }, function () { return state != 'inactive' } ],
];
var sizer = new wxStaticBoxSizer(new wxStaticBox(window, -1, 'Simulation test'), wxOrientation.HORIZONTAL);
for each (var b in buttons)
{
var button = new wxButton(window, -1, b[0]);
button.onClicked = b[1];
sizer.add(button, 1);
b[3] = button;
}
updateEnableStatus();
window.sizer.add(sizer, 0, wxStretch.EXPAND | wxDirection.LEFT|wxDirection.RIGHT, 2);
}
//TODO: Would be nicer not to use an extra settings property, this is to avoid the observer data getting written to maps
// perhaps that single element can be excluded
var defaults = {
mapSettings : {
settings: {
Name: 'Untitled',
Description : '',
PlayerData : []
}
}
};
var g_observer;
// Flag if we should only notify other scripts not this one (prevents recursion)
var g_externalNotify;
// Merges the 'defs' tree into 'obj', overwriting any old values with
// the same keys
function setDefaults(defs, obj)
{
if (defs instanceof Object)
{
for (var k in defs) {
if (obj instanceof Object && k in obj)
setDefaults(defs[k], obj[k]);
else
obj[k] = defs[k];
}
}
}
// Read civ data and player defaults
function loadCivData()
{
// Load civilization data
Atlas.State.CivData = [];
Atlas.State.CivNames = [];
Atlas.State.CivCodes = [];
var dataArray = Atlas.Message.GetCivData().data;
if (dataArray)
{ // parse JSON strings into objects
for (var i = 0; i < dataArray.length; ++i)
{
var civ = JSON.parse(dataArray[i]);
if (civ)
{
Atlas.State.CivData.push(civ);
Atlas.State.CivNames.push(civ.Name);
Atlas.State.CivCodes.push(civ.Code);
}
}
}
}
function loadPlayerDefaults()
{
// Load player default data (names, civs, colors, etc)
Atlas.State.PlayerDefaults = [];
var rawData = Atlas.Message.GetPlayerDefaults().defaults;
if(rawData)
{
Atlas.State.PlayerDefaults = JSON.parse(rawData).PlayerData;
}
}
function getMapSettings()
{
// Get map settings to populate GUI
var settings = Atlas.Message.GetMapSettings().settings;
if (settings)
{
Atlas.State.mapSettings.settings = JSON.parse(settings);
}
}
function makeObservable(obj)
{
// If the object has already been set up as observable, don't do any more work.
// (In particular, don't delete any old observers, so they don't get lost when
// this script is reloaded.)
if (typeof obj._observers != 'undefined')
return;
obj._observers = [];
obj.registerObserver = function (callback) {
this._observers.push(callback);
}
obj.unregisterObserver = function (callback) {
this._observers = this._observers.filter(function (o) { return o !== callback });
}
obj.notifyObservers = function () {
for each (var o in this._observers)
o(this);
};
}
function init(window)
{
window.sizer = new wxBoxSizer(wxOrientation.VERTICAL);
// Don't overwrite old data when script is hotloaded
setDefaults(defaults, Atlas.State);
///////////////////////////////////////////////////////////////////////
// Map setting controls
// Map name
var settingsSizer = new wxStaticBoxSizer(new wxStaticBox(window, -1, 'Map settings'), wxOrientation.VERTICAL);
var boxSizer = new wxBoxSizer(wxOrientation.HORIZONTAL);
boxSizer.add(new wxStaticText(window, -1, 'Name'), 0, wxAlignment.CENTER_VERTICAL);
boxSizer.add(10, 0);
var mapNameCtrl = new wxTextCtrl(window, -1, 'Untitled');
mapNameCtrl.toolTip = "Enter a name for the map here";
mapNameCtrl.onText = function(evt)
{
Atlas.State.mapSettings.settings.Name = evt.string;
};
boxSizer.add(mapNameCtrl, 1);
function updateMapName()
{
mapNameCtrl.value = Atlas.State.mapSettings.settings.Name ? Atlas.State.mapSettings.settings.Name : 'Untitled';
}
settingsSizer.add(boxSizer, 0, wxStretch.EXPAND);
settingsSizer.add(5, 5, 0); // Add space
// Map description
boxSizer = new wxBoxSizer(wxOrientation.VERTICAL);
boxSizer.add(new wxStaticText(window, -1, 'Description'), wxAlignment.RIGHT);
var mapDescCtrl = new wxTextCtrl(window, -1, '', wxDefaultPosition, new wxSize(-1, 100), wxTextCtrl.MULTILINE);
mapDescCtrl.toolTip = "Enter an interesting description for the map here";
mapDescCtrl.onText = function(evt)
{
Atlas.State.mapSettings.settings.Description = evt.string;
};
boxSizer.add(mapDescCtrl, 0, wxStretch.EXPAND);
function updateMapDesc()
{
mapDescCtrl.value = Atlas.State.mapSettings.settings.Description ? Atlas.State.mapSettings.settings.Description : '';
}
settingsSizer.add(boxSizer, 0, wxStretch.EXPAND);
settingsSizer.add(5, 5, 0); // Add space
// Reveal map
boxSizer = new wxBoxSizer(wxOrientation.HORIZONTAL);
boxSizer.add(new wxStaticText(window, -1, 'Reveal map'), wxAlignment.LEFT);
boxSizer.add(10, 0);
var revealMapCtrl = new wxCheckBox(window, -1, '');
revealMapCtrl.toolTip = 'If checked, players will see the whole map explored and their enemies';
revealMapCtrl.onCheckBox = function(evt)
{
Atlas.State.mapSettings.settings.RevealMap = evt.checked;
};
boxSizer.add(revealMapCtrl);
function updateRevealMap()
{ // Defaults to false if setting doesn't exist
revealMapCtrl.value = Atlas.State.mapSettings.settings.RevealMap;
}
settingsSizer.add(boxSizer, 0, wxStretch.EXPAND);
settingsSizer.add(5, 5, 0); // Add space
// Game type
boxSizer = new wxBoxSizer(wxOrientation.HORIZONTAL);
boxSizer.add(new wxStaticText(window, -1, 'Game type'), 0, wxAlignment.CENTER_VERTICAL);
boxSizer.add(10, 0);
var gameTypes = ["conquest", "endless"];
var gameTypeCtrl = new wxChoice(window, -1, wxDefaultPosition, new wxSize(100,-1), gameTypes);
gameTypeCtrl.toolTip = 'Select the game type / victory conditions';
gameTypeCtrl.onChoice = function (evt)
{
if (evt.selection != -1)
{
Atlas.State.mapSettings.settings.GameType = evt.string;
}
};
boxSizer.add(gameTypeCtrl);
function updateGameType()
{
var idx = Atlas.State.mapSettings.settings.GameType ? gameTypes.indexOf(Atlas.State.mapSettings.settings.GameType) : 0;
gameTypeCtrl.selection = idx;
}
settingsSizer.add(boxSizer, 0, wxStretch.EXPAND);
settingsSizer.add(5, 5, 0); // Add space
// Number of players
boxSizer = new wxBoxSizer(wxOrientation.HORIZONTAL);
boxSizer.add(new wxStaticText(window, -1, 'Number of Players'), 0, wxAlignment.CENTER_VERTICAL);
boxSizer.add(10, 0);
var numPlayers = new wxSpinCtrl(window, -1, '8', wxDefaultPosition, new wxSize(40, -1));
numPlayers.toolTip = 'Select the number of players on this map';
numPlayers.setRange(1, 8);
numPlayers.onSpinCtrl = function(evt)
{
// Adjust player data accordingly
if (!Atlas.State.mapSettings.settings.PlayerData)
Atlas.State.mapSettings.settings.PlayerData = [];
Atlas.State.numPlayers = evt.position;
var curPlayers = Atlas.State.mapSettings.settings.PlayerData.length;
if (curPlayers < evt.position)
{ // Add extra players from default
for (var i = curPlayers; i < evt.position; ++i)
{
Atlas.State.mapSettings.settings.PlayerData.push(Atlas.State.PlayerDefaults[i]);
}
}
else
{ //Remove extra players
Atlas.State.mapSettings.settings.PlayerData = Atlas.State.mapSettings.settings.PlayerData.slice(0, evt.position);
}
g_externalNotify = true;
Atlas.State.mapSettings.notifyObservers();
g_externalNotify = false;
};
boxSizer.add(numPlayers);
function updateNumPlayers()
{
numPlayers.value = Atlas.State.mapSettings.settings.PlayerData ? Atlas.State.mapSettings.settings.PlayerData.length : 8;
}
settingsSizer.add(boxSizer, 0, wxStretch.EXPAND);
window.sizer.add(settingsSizer, 0, wxStretch.EXPAND | wxDirection.LEFT|wxDirection.RIGHT, 2);
///////////////////////////////////////////////////////////////////////
// Keyword list
var keywordSizer = new wxStaticBoxSizer(new wxStaticBox(window, -1, 'Keywords'), wxOrientation.VERTICAL);
boxSizer = new wxBoxSizer(wxOrientation.HORIZONTAL);
boxSizer.add(new wxStaticText(window, -1, 'Demo'));
boxSizer.add(5, 0);
var demoCtrl = new wxCheckBox(window, -1, '');
demoCtrl.tooltip = 'Toggle \'demo\' keyword';
demoCtrl.onCheckBox = function(evt)
{
applyKeyword(evt.checked, 'demo');
};
boxSizer.add(demoCtrl);
keywordSizer.add(boxSizer, 0, wxStretch.EXPAND);
keywordSizer.add(0, 5);
boxSizer = new wxBoxSizer(wxOrientation.HORIZONTAL);
boxSizer.add(new wxStaticText(window, -1, 'Hidden'));
boxSizer.add(5, 0);
var hiddenCtrl = new wxCheckBox(window, -1, '');
hiddenCtrl.tooltip = 'Toggle \'hidden\' keyword';
hiddenCtrl.onCheckBox = function(evt)
{
applyKeyword(evt.checked, 'hidden');
};
boxSizer.add(hiddenCtrl);
keywordSizer.add(boxSizer, 0, wxStretch.EXPAND);
function applyKeyword(flag, keyword)
{
var idx = Atlas.State.mapSettings.settings.Keywords.indexOf(keyword);
if (flag && idx == -1)
{ // Add keyword
Atlas.State.mapSettings.settings.Keywords.push(keyword);
}
else if (!flag && idx != -1)
{ // Remove keyword
Atlas.State.mapSettings.settings.Keywords.splice(idx, 1);
}
}
function updateKeywords()
{
if (!Atlas.State.mapSettings.settings.Keywords)
{
Atlas.State.mapSettings.settings.Keywords = [];
}
demoCtrl.value = (Atlas.State.mapSettings.settings.Keywords && Atlas.State.mapSettings.settings.Keywords.indexOf('demo') != -1);
hiddenCtrl.value = (Atlas.State.mapSettings.settings.Keywords && Atlas.State.mapSettings.settings.Keywords.indexOf('hidden') != -1);
}
window.sizer.add(keywordSizer, 0, wxStretch.EXPAND | wxDirection.LEFT|wxDirection.RIGHT, 2);
///////////////////////////////////////////////////////////////////////
// Random map controls
var rmsPanel = new wxPanel(window, -1);
var rmsSizer = new wxStaticBoxSizer(new wxStaticBox(rmsPanel, -1, 'Random map'), wxOrientation.VERTICAL);
boxSizer = new wxBoxSizer(wxOrientation.HORIZONTAL);
var rmsChoice = new wxChoice(rmsPanel, -1, wxDefaultPosition, wxDefaultSize, []);
rmsChoice.toolTip = "Select the random map script to run";
function loadScriptChoices()
{
// Reload RMS data
Atlas.State.scriptNames = [];
Atlas.State.scriptData = [];
// Get array of RMS data
var rawData = Atlas.Message.GetRMSData().data;
for (var i = 0; i < rawData.length; ++i)
{
// Parse JSON strings to objects
var data = JSON.parse(rawData[i]);
if (data && data.settings)
{
Atlas.State.scriptData.push(data);
Atlas.State.scriptNames.push(data.settings.Name);
}
}
// Add script names to choice control
rmsChoice.clear();
rmsChoice.append(Atlas.State.scriptNames);
rmsChoice.selection = 0;
}
boxSizer.add(rmsChoice, 1, wxAlignment.CENTER_VERTICAL);
boxSizer.add(5, 0);
var rmsReload = new wxButton(rmsPanel, -1, 'R', wxDefaultPosition, new wxSize(20, -1));
rmsReload.toolTip = 'Click to refresh random map list';
rmsReload.onClicked = function()
{
loadScriptChoices();
};
boxSizer.add(rmsReload, 0, wxAlignment.CENTER_VERTICAL);
rmsSizer.add(boxSizer, 0, wxStretch.EXPAND | wxDirection.ALL, 2);
boxSizer = new wxBoxSizer(wxOrientation.HORIZONTAL);
boxSizer.add(new wxStaticText(rmsPanel, -1, 'Map size'), 0, wxAlignment.CENTER_VERTICAL);
boxSizer.add(10, 0);
// TODO: Get this data from single location (currently specified here, Atlas\lists.xml, and game setup)
var sizeNames = ["Tiny", "Small", "Medium", "Normal", "Large", "Very Large", "Giant"];
var sizeTiles = [128, 192, 256, 320, 384, 448, 512];
var sizeChoice = new wxChoice(rmsPanel, -1, wxDefaultPosition, wxDefaultSize, sizeNames);
var numChoices = sizeNames.length;
sizeChoice.toolTip = 'Select the desired map size\n'+sizeNames[0]+' = '+sizeTiles[0]+' patches, '+sizeNames[numChoices-1]+' = '+sizeTiles[numChoices-1]+' patches';
sizeChoice.selection = 0;
boxSizer.add(sizeChoice, 1);
rmsSizer.add(boxSizer, 0, wxStretch.EXPAND | wxDirection.ALL, 2);
boxSizer = new wxBoxSizer(wxOrientation.HORIZONTAL);
var generateBtn = new wxButton(rmsPanel, -1, 'Generate');
generateBtn.toolTip = 'Generate random map using selected script';
generateBtn.onClicked = function ()
{
var selection = rmsChoice.selection;
if (selection != -1)
{
var RMSData = Atlas.State.scriptData[selection].settings;
if (RMSData)
{
if (useRandomCtrl.value)
{ // Generate random seed
generateRandomSeed();
}
// Copy RMS data to map settings
for (var prop in RMSData)
{
Atlas.State.mapSettings.settings[prop] = RMSData[prop];
}
// Complete map settings
Atlas.State.mapSettings.settings.Seed = Atlas.State.Seed ? Atlas.State.Seed : 0;
Atlas.State.mapSettings.settings.Size = sizeTiles[sizeChoice.selection];
// TODO: Would be nice to have some sort of busy notification here
// Generate map
var ret = Atlas.Message.GenerateMap(RMSData.Script, JSON.stringify(Atlas.State.mapSettings.settings));
// Check for error
if (ret.status < 0)
{
wxMessageBox("Random map script '"+RMSData.Script+"' failed. Loading blank map.");
Atlas.Message.LoadMap("_default");
}
Atlas.State.mapSettings.notifyObservers();
}
}
};
boxSizer.add(generateBtn, 0);
boxSizer.add(5, 0);
boxSizer.add(new wxStaticText(rmsPanel, -1, 'Random seed'), 0, wxAlignment.CENTER_VERTICAL);
boxSizer.add(5, 0);
var useRandomCtrl = new wxCheckBox(rmsPanel, -1, '');
useRandomCtrl.toolTip = 'Always generate a new random seed';
useRandomCtrl.value = true;
boxSizer.add(useRandomCtrl, 0, wxAlignment.CENTER_VERTICAL);
rmsSizer.add(boxSizer, 0, wxStretch.EXPAND | wxDirection.ALL, 2);
boxSizer = new wxBoxSizer(wxOrientation.HORIZONTAL);
boxSizer.add(new wxStaticText(rmsPanel, -1, 'Seed'), 0, wxAlignment.CENTER_VERTICAL);
boxSizer.add(10, 0);
var seedCtrl = new wxTextCtrl(rmsPanel, -1, '', wxDefaultPosition, new wxSize(60,-1));
seedCtrl.toolTip = 'Enter a numeric seed value here';
seedCtrl.onText = function()
{
var num = parseInt(this.value, 10);
if (!isNaN(num))
{
Atlas.State.Seed = num;
}
else
{
// TODO: Can allow text by hashing it into a seed value - for fun?
}
};
boxSizer.add(seedCtrl, 1);
function generateRandomSeed()
{
seedCtrl.value = Math.floor(Math.random() * 2147483648)+ 1;
}
rmsSizer.add(boxSizer, 0, wxStretch.EXPAND | wxDirection.ALL, 2);
// TODO: Possibly have controls for base height + terrain to override RMS
rmsPanel.sizer = rmsSizer;
window.sizer.add(rmsPanel, 0, wxStretch.EXPAND | wxDirection.LEFT|wxDirection.RIGHT, 2);
///////////////////////////////////////////////////////////////////////
// Simulation controls
setupSimTest(window, rmsPanel);
// Initial seed
seedCtrl.value = 0;
g_observer = function()
{
if (!g_externalNotify)
{
// We have to do these steps here, because the simulation is not
// initialized when this script is first loaded
// If we don't have civ data, load those
if (!Atlas.State.CivData)
{
loadCivData();
}
// If we don't have default player data, load those
if (!Atlas.State.PlayerDefaults)
{
loadPlayerDefaults();
}
// If we don't have RMS data yet, load those
if (!Atlas.State.scriptData)
{
loadScriptChoices();
}
// Load map settings from engine
getMapSettings();
// Update UI controls
updateMapName();
updateMapDesc();
updateRevealMap();
updateGameType();
updateNumPlayers();
updateKeywords();
}
}
// Set up observers (so that this script can be notified when map data is loaded)
makeObservable(Atlas.State.mapSettings);
Atlas.State.mapSettings.registerObserver(g_observer);
}
function deinit()
{
Atlas.State.mapSettings.unregisterObserver(g_observer);
}

View File

@ -1,353 +0,0 @@
function setObjectFilter(objectList, objects, type)
{
objectList.freeze();
objectList.clear();
var ids = [];
for each (var object in objects) {
if (object.type == type) {
ids.push(object.id);
objectList.append(object.name);
}
}
objectList.objectIDs = ids;
objectList.thaw();
}
var actorViewer = {
active: false,
distance: 20,
angle: 0,
elevation: Math.PI / 6,
actor: "actor|structures/fndn_1x1.xml",
animation: "idle",
// Animation playback speed
speed: 0,
// List of controls which should be hidden, and only shown when the Actor Viewer is active
controls: []
};
actorViewer.toggle = function () {
if (this.active) {
// TODO: maybe this should switch back to whatever was selected before,
// not necessarily PlaceObject
Atlas.SetCurrentToolWith('PlaceObject', this.actor);
} else {
Atlas.SetCurrentToolWithVal('ScriptedTool', this);
}
};
actorViewer.postToGame = function () {
Atlas.Message.SetActorViewer(this.actor, this.animation, this.speed, false);
};
actorViewer.postLookAt = function () {
var offset = 0.3; // slight fudge so we turn nicely when going over the top of the unit
var pos = {
x: this.distance*Math.cos(this.elevation)*Math.sin(this.angle) + offset*Math.cos(this.angle),
y: this.distance*Math.sin(this.elevation),
z: this.distance*Math.cos(this.elevation)*Math.cos(this.angle) - offset*Math.sin(this.angle)
};
Atlas.Message.LookAt(Atlas.RenderView.ACTOR, pos, {x:0, y:0, z:0});
};
actorViewer.setActor = function (actor) {
this.actor = actor;
if (this.active) {
this.postToGame();
Atlas.State.objectSettings.onSelectionChange();
}
}
actorViewer.onEnable = function () {
this.active = true;
this.button.label = this.buttonTextActive;
for each (ctrl in actorViewer.controls)
ctrl.show(true);
this.postToGame();
Atlas.State.objectSettings.view = Atlas.RenderView.ACTOR;
Atlas.State.objectSettings.selectedObjects = [0];
Atlas.State.objectSettings.onSelectionChange(); // (must come after postToGame)
this.postLookAt();
Atlas.Message.RenderEnable(Atlas.RenderView.ACTOR);
}
actorViewer.onDisable = function () {
this.active = false;
this.button.label = this.buttonTextInactive;
for each (ctrl in actorViewer.controls)
ctrl.show(false);
Atlas.State.objectSettings.view = Atlas.RenderView.GAME;
Atlas.State.objectSettings.selectedObjects = [];
Atlas.State.objectSettings.onSelectionChange();
Atlas.Message.RenderEnable(Atlas.RenderView.GAME);
}
actorViewer.onKey = function (evt, type) {
var code0 = '0'.charCodeAt(0);
var code9 = '9'.charCodeAt(0);
if (type == 'down' && evt.keyCode >= code0 && evt.keyCode <= code9) {
// (TODO: this should probably be 'char' not 'down'; but we don't get
// 'char' unless we return false from this function, in which case the
// scenario editor intercepts some other keys for itself)
Atlas.State.objectSettings.playerID = evt.keyCode - code0;
Atlas.State.objectSettings.notifyObservers();
}
// Prevent keys from passing through to the scenario editor
return true;
}
actorViewer.onMouse = function (evt) {
var cameraChanged = false;
var speedModifier = this.getSpeedModifier();
if (evt.wheelRotation) {
var speed = -1 * speedModifier;
this.distance += evt.wheelRotation * speed / evt.wheelDelta;
cameraChanged = true;
}
if (evt.leftDown || evt.rightDown) {
this.mouseLastX = evt.x;
this.mouseLastY = evt.y;
this.mouseLastValid = true;
} else if (evt.dragging && this.mouseLastValid && (evt.leftIsDown || evt.rightIsDown)) {
var dx = evt.x - this.mouseLastX;
var dy = evt.y - this.mouseLastY;
this.mouseLastX = evt.x;
this.mouseLastY = evt.y;
this.angle += dx * Math.PI/256 * speedModifier;
if (evt.leftIsDown)
this.distance += (dy / 8) * speedModifier;
else // evt.rightIsDown
this.elevation += (dy * Math.PI/256) * speedModifier;
cameraChanged = true;
} else if ((evt.leftUp || evt.rightUp) && ! (evt.leftDown || evt.rightDown)) {
// In some situations (e.g. double-clicking the title bar to
// maximise the window) we get a dragging event without the matching
// buttondown; so disallow dragging when all buttons were released since
// the last buttondown.
// (TODO: does this problem affect the scenario editor too?)
this.mouseLastValid = false;
}
if (cameraChanged) {
this.distance = Math.max(this.distance, 1/64); // don't let people fly through the origin
this.postLookAt();
}
return true;
};
actorViewer.getSpeedModifier = function () { // TODO: this should be shared with the rest of the application
if (wxGetKeyState(wxKeyCode.SHIFT) && wxGetKeyState(wxKeyCode.CONTROL))
return 1/64;
else if (wxGetKeyState(wxKeyCode.CONTROL))
return 1/4;
else if (wxGetKeyState(wxKeyCode.SHIFT))
return 4;
else
return 1;
};
var g_observer;
function init(window, bottomWindow)
{
window.sizer = new wxBoxSizer(wxOrientation.VERTICAL);
var objects = Atlas.Message.GetObjectsList().objects;
var objectList = new wxListBox(window, -1, wxDefaultPosition, wxDefaultSize, [],
wxListBox.SINGLE | wxListBox.HSCROLL);
var objectType = 0;
objectList.onListBox = function (evt) {
if (evt.selection == -1)
return;
var id = objectList.objectIDs[evt.selection];
actorViewer.setActor(id);
if (! actorViewer.active)
Atlas.SetCurrentToolWith('PlaceObject', id);
};
setObjectFilter(objectList, objects, objectType);
var groupSelector = new wxChoice(window, -1, wxDefaultPosition, wxDefaultSize,
["Entities", "Actors (all)"]
);
groupSelector.onChoice = function (evt) {
objectType = evt.selection;
setObjectFilter(objectList, objects, objectType);
};
window.sizer.add(groupSelector, 0, wxStretch.EXPAND);
window.sizer.add(objectList, 1, wxStretch.EXPAND);
var viewerButton = new wxButton(window, -1, "Switch to Actor Viewer");
actorViewer.button = viewerButton;
actorViewer.buttonTextInactive = "Switch to Actor Viewer";
actorViewer.buttonTextActive = "Switch to game view";
viewerButton.onClicked = function () { actorViewer.toggle(); }
window.sizer.add(viewerButton, 0, wxStretch.EXPAND);
// Actor viewer settings:
var displaySettingsBoxBox = new wxStaticBox(bottomWindow, -1, "Display settings");
actorViewer.controls.push(displaySettingsBoxBox);
var displaySettingsBox = new wxStaticBoxSizer(displaySettingsBoxBox, wxOrientation.VERTICAL);
displaySettingsBox.minSize = new wxSize(140, -1);
var displaySettings = [
["Wireframe", "Toggle wireframe / solid rendering", "wireframe", false],
["Move", "Toggle movement along ground when playing walk/run animations", "walk", false],
["Ground", "Toggle the ground plane", "ground", true],
["Shadows", "Toggle shadow rendering", "shadows", true],
["Poly count", "Toggle polygon-count statistics - turn off ground and shadows for more useful data", "stats", false]
];
// NOTE: there's also a background colour setting, which isn't exposed
// by this UI because I don't know if it's worth the effort
for each (var setting in displaySettings) {
var button = new wxButton(bottomWindow, -1, setting[0]);
actorViewer.controls.push(button);
button.toolTip = setting[1];
// Set the default value
Atlas.Message.SetViewParamB(Atlas.RenderView.ACTOR, setting[2], setting[3]);
// Toggle the value on clicks
(function (s) { // local scope for closure
button.onClicked = function () {
s[3] = !s[3];
Atlas.Message.SetViewParamB(Atlas.RenderView.ACTOR, s[2], s[3]);
};
})(setting);
displaySettingsBox.add(button, 0, wxStretch.EXPAND);
}
// TODO: It might be nice to add an "edit this actor" button
// in the actor viewer (when we have working actor hotloading)
var playerSelector = new wxChoice(bottomWindow, -1, wxDefaultPosition, wxDefaultSize,
["Gaia", "Player 1", "Player 2", "Player 3", "Player 4", "Player 5", "Player 6", "Player 7", "Player 8"]
);
playerSelector.selection = Atlas.State.objectSettings.playerID;
playerSelector.onChoice = function (evt) {
Atlas.State.objectSettings.playerID = evt.selection;
Atlas.State.objectSettings.notifyObservers();
};
function updatePlayerSelector() {
playerSelector.selection = Atlas.State.objectSettings.playerID;
}
var animationBoxBox = new wxStaticBox(bottomWindow, -1, "Animation");
actorViewer.controls.push(animationBoxBox);
var animationBox = new wxStaticBoxSizer(animationBoxBox, wxOrientation.VERTICAL);
var animationSelector = new wxChoice(bottomWindow, -1, wxDefaultPosition, wxDefaultSize,
[ "idle", "walk", "run", "melee", "death", "build",
"gather_fruit", "gather_grain", "gather_meat",
"gather_tree", "gather_rock", "gather_ore", "gather_ruins", "gather_treasure" ] // TODO: this list should come from the actor
);
animationSelector.stringSelection = "idle";
actorViewer.controls.push(animationSelector);
animationSelector.onChoice = function (evt) {
actorViewer.animation = evt.string;
actorViewer.postToGame();
};
var animationSpeedSizer = new wxBoxSizer(wxOrientation.HORIZONTAL);
var speeds = [ ['Play', 1], ['Pause', 0], ['Slow', 0.1] ];
for each (var speed in speeds) {
var button = new wxButton(bottomWindow, -1, speed[0], wxDefaultPosition, new wxSize(50, -1));
actorViewer.controls.push(button);
(function (s) { // local scope for closure
button.onClicked = function () {
actorViewer.speed = s;
actorViewer.postToGame();
};
})(speed[1]);
animationSpeedSizer.add(button);
}
animationBox.add(animationSelector, 0, wxStretch.EXPAND);
animationBox.add(animationSpeedSizer, 0, wxStretch.EXPAND);
var animationSizer = new wxBoxSizer(wxOrientation.VERTICAL);
animationSizer.minSize = new wxSize(160, -1);
animationSizer.add(playerSelector, 0, wxStretch.EXPAND);
animationSizer.add(animationBox, 0, wxStretch.EXPAND);
for each (ctrl in actorViewer.controls)
ctrl.show(false);
var variationControl = new wxScrolledWindow(bottomWindow, -1);
variationControl.setScrollRate(0, 5);
variationControl.sizer = new wxBoxSizer(wxOrientation.VERTICAL);
var variationControlBox = new wxStaticBoxSizer(new wxStaticBox(bottomWindow, -1, "Actor Variation"), wxOrientation.VERTICAL);
variationControl.sizer.minSize = new wxSize(160, -1);
variationControlBox.add(variationControl, 1);
function onVariationSelect() {
// It's possible for a variant name to appear in multiple groups.
// If so, assume that all the names in each group are the same, so
// we don't have to worry about some impossible combinations (e.g.
// one group "a,b", a second "b,c", and a third "c,a", where's there's
// no set of selections that matches one (and only one) of each group).
//
// So... When a combo box is changed from 'a' to 'b', add 'b' to the new
// selections and make sure any other combo boxes containing both 'a' and
// 'b' no longer contain 'a'.
var sel = this.stringSelection;
var selections = [ sel ];
for each (var c in variationControl.children)
if (c.findString(sel) == wxNOT_FOUND)
selections.push(c.stringSelection);
Atlas.State.objectSettings.actorSelections = selections;
Atlas.State.objectSettings.notifyObservers();
}
function updateVariationControl() {
variationControl.freeze();
variationControl.sizer.clear(true);
var settings = Atlas.State.objectSettings;
var variation = settings.getActorVariation();
for (var i = 0; i < settings.variantgroups.length; ++i) {
var choice = new wxChoice(variationControl, -1, wxDefaultPosition, new wxSize(80, -1),
settings.variantgroups[i]);
choice.onChoice = onVariationSelect;
choice.stringSelection = variation[i];
variationControl.sizer.add(choice, 0, wxStretch.EXPAND);
}
// TODO: this sizer stuff is a bit dodgy - it often doesn't quite
// update the sizes and scrollbars at the right points
variationControl.thaw();
variationControlBox.layout();
variationControl.sizer.layout();
bottomWindow.sizer.layout();
}
bottomWindow.sizer = new wxBoxSizer(wxOrientation.HORIZONTAL);
bottomWindow.sizer.add(displaySettingsBox);
bottomWindow.sizer.add(animationSizer);
bottomWindow.sizer.add(variationControlBox, 0, wxStretch.EXPAND);
g_observer = function() {
updatePlayerSelector();
updateVariationControl();
};
Atlas.State.objectSettings.registerObserver(g_observer);
// Initialise the controls
g_observer();
}
function deinit()
{
Atlas.State.objectSettings.unregisterObserver(g_observer);
}

View File

@ -1,192 +0,0 @@
var brushShapes = {
'circle': {
width: function (size) { return size },
height: function (size) { return size },
data: function (size) {
var data = [];
// All calculations are done in units of half-tiles, since that
// is the required precision
var mid_x = size-1;
var mid_y = size-1;
var scale = 1 / (Math.sqrt(2) - 1);
for (var y = 0; y < size; ++y)
{
for (var x = 0; x < size; ++x)
{
var dist_sq = // scaled to 0 in centre, 1 on edge
((2*x - mid_x)*(2*x - mid_x) +
(2*y - mid_y)*(2*y - mid_y)) / (size*size);
if (dist_sq <= 1)
data.push((Math.sqrt(2 - dist_sq) - 1) * scale);
else
data.push(0);
}
}
return data;
}
},
'square': {
width: function (size) { return size },
height: function (size) { return size },
data: function (size) {
var data = [];
for (var i = 0; i < size*size; ++i)
data.push(1);
return data;
}
}
};
var brush = {
shape: brushShapes['circle'],
size: 4,
strength: 1.0,
active: false,
send: function () {
Atlas.Message.Brush(
this.shape.width(this.size),
this.shape.height(this.size),
this.shape.data(this.size)
);
// TODO: rather than this hack to make things interact correctly with C++ tools,
// implement the tools in JS and do something better
Atlas.SetBrushStrength(this.strength);
}
};
function init(window, bottomWindow)
{
window.sizer = new wxBoxSizer(wxOrientation.VERTICAL);
var tools = [
{ label: 'Modify', name: 'AlterElevation' },
{ label: 'Smooth', name: 'SmoothElevation' },
{ label: 'Flatten', name: 'FlattenElevation' },
{ label: 'Paint', name: 'PaintTerrain' },
];
var selectedTool = null; // null if none selected, else an element of 'tools'
var toolSizer = new wxStaticBoxSizer(new wxStaticBox(window, -1, 'Elevation tools'), wxOrientation.HORIZONTAL);
window.sizer.add(toolSizer, 0, wxStretch.EXPAND);
for each (var tool in tools)
{
var button = new wxButton(window, -1, tool.label);
toolSizer.add(button, 1);
tool.button = button;
// Explicitly set the background to the default colour, so that the button
// is always owner-drawn (by the wxButton code), rather than initially using the
// native (standard colour) button appearance then changing inconsistently later.
button.backgroundColour = wxSystemSettings.getColour(wxSystemSettings.COLOUR_BTNFACE);
(function(tool) { // (local scope)
button.onClicked = function () {
if (selectedTool == tool)
{
// Clicking on one tool twice should disable it
selectedTool = null;
this.backgroundColour = wxSystemSettings.getColour(wxSystemSettings.COLOUR_BTNFACE);
Atlas.SetCurrentTool('');
}
else
{
// Disable the old tool
if (selectedTool)
selectedTool.button.backgroundColour = wxSystemSettings.getColour(wxSystemSettings.COLOUR_BTNFACE);
// Enable the new one
selectedTool = tool;
this.backgroundColour = new wxColour(0xEE, 0xCC, 0x55);
Atlas.SetCurrentTool(tool.name);
brush.send();
}
};
})(tool);
// TODO: Need to make this interact properly with Tools.cpp/RegisterToolButton so all the buttons are in sync
}
var brushSizer = new wxStaticBoxSizer(new wxStaticBox(window, -1, 'Brush'), wxOrientation.VERTICAL);
window.sizer.add(brushSizer);
var shapes = [
[ 'Circle', brushShapes['circle'] ],
[ 'Square', brushShapes['square'] ]
];
var shapeNames = [];
for each (var s in shapes) shapeNames.push(s[0]);
var shapeBox = new wxRadioBox(window, -1, 'Shape', wxDefaultPosition, wxDefaultSize, shapeNames, 0, wxRadioBox.SPECIFY_ROWS);
brushSizer.add(shapeBox);
shapeBox.onRadioBox = function(evt)
{
brush.shape = shapes[evt.integer][1];
brush.send();
};
var brushSettingsSizer = new wxFlexGridSizer(2);
brushSizer.add(brushSettingsSizer);
brushSettingsSizer.add(new wxStaticText(window, -1, 'Size'), 0, wxAlignment.RIGHT);
var sizeSpinner = new wxSpinCtrl(window, -1, 4, wxDefaultPosition, wxDefaultSize, wxSpinCtrl.ARROW_KEYS, 1, 100);
brushSettingsSizer.add(sizeSpinner);
sizeSpinner.onSpinCtrl = function(evt)
{
brush.size = evt.position;
brush.send();
};
brushSettingsSizer.add(new wxStaticText(window, -1, 'Strength'), wxAlignment.RIGHT);
var strengthSpinner = new wxSpinCtrl(window, -1, 10, wxDefaultPosition, wxDefaultSize, wxSpinCtrl.ARROW_KEYS, 1, 100);
brushSettingsSizer.add(strengthSpinner);
strengthSpinner.onSpinCtrl = function(evt)
{
brush.strength = evt.position / 10;
brush.send();
};
var visualiseSizer = new wxStaticBoxSizer(new wxStaticBox(window, -1, 'Visualise'), wxOrientation.VERTICAL);
window.sizer.add(visualiseSizer);
var visualiseSettingsSizer = new wxFlexGridSizer(2);
visualiseSizer.add(visualiseSettingsSizer);
visualiseSettingsSizer.add(new wxStaticText(window, -1, 'Passability'), 0, wxAlignment.RIGHT);
var passabilityClasses = Atlas.Message.GetTerrainPassabilityClasses().classNames;
var passabilitySelector = new wxChoice(window, -1, wxDefaultPosition, wxDefaultSize,
["(none)"].concat(passabilityClasses)
);
passabilitySelector.selection = 0;
visualiseSettingsSizer.add(passabilitySelector);
passabilitySelector.onChoice = function (evt) {
if (evt.selection == 0)
Atlas.Message.SetViewParamS(Atlas.RenderView.GAME, "passability", "");
else
Atlas.Message.SetViewParamS(Atlas.RenderView.GAME, "passability", evt.string);
};
visualiseSettingsSizer.add(new wxStaticText(window, -1, 'Priorities'), 0, wxAlignment.RIGHT);
var priorityCheckbox = new wxCheckBox(window, -1, "");
visualiseSettingsSizer.add(priorityCheckbox);
priorityCheckbox.onCheckBox = function (evt) {
Atlas.Message.SetViewParamB(Atlas.RenderView.GAME, "priorities", evt.checked);
};
var terrainGroups = Atlas.Message.GetTerrainGroups();
var nb = new wxNotebook(bottomWindow, -1);
bottomWindow.sizer = new wxBoxSizer(wxOrientation.VERTICAL);
bottomWindow.sizer.add(nb, 1, wxStretch.EXPAND);
var pages = [];
nb.onPageChanged = function (evt) {
pages[evt.selection].display()
evt.skip = true;
}
for each (var groupName in terrainGroups.groupNames)
{
var panel = new wxPanel(nb, -1);
var page = new global.TerrainPreviewPage(panel, groupName);
pages.push(page);
nb.addPage(panel, groupName); // TODO: use Titlecase letters
}
}

View File

@ -1,21 +0,0 @@
function init(window)
{
var terrainGroups = Atlas.Message.GetTerrainGroups();
var nb = new wxNotebook(window, -1);
window.sizer = new wxBoxSizer(wxOrientation.VERTICAL);
window.sizer.add(nb, 1, wxStretch.EXPAND);
var pages = [];
nb.onPageChanged = function (evt) {
pages[evt.selection].display()
evt.skip = true;
}
for each (var groupName in terrainGroups.groupNames)
{
var panel = new wxPanel(nb, -1);
var page = new global.TerrainPreviewPage(panel, groupName);
pages.push(page);
nb.addPage(panel, groupName); // TODO: use Titlecase letters
}
}

View File

@ -784,25 +784,6 @@ function setup_atlas_packages()
},{ -- extra_params
})
setup_atlas_package("wxJS", "lib",
{ -- src
"",
"common",
"ext",
"gui",
"gui/control",
"gui/event",
"gui/misc",
"io",
},{ -- include
},{ -- extern_libs
"spidermonkey",
"wxwidgets"
},{ -- extra_params
pch = (not has_broken_pch),
no_unused_warnings = 1, -- wxJS has far too many and we're never going to fix them, so just ignore them
})
atlas_src = {
"ActorEditor",
"ColourTester",
@ -834,7 +815,6 @@ function setup_atlas_packages()
atlas_extra_links = {
"AtlasObject",
"AtlasScript",
"wxJS",
}
if options["aoe3ed"] then
tinsert(atlas_src, "ArchiveViewer")

View File

@ -31,16 +31,6 @@
#include "wx/wx.h"
#include "wxJS/common/main.h"
#include "wxJS/ext/wxjs_ext.h"
#include "wxJS/io/init.h"
#include "wxJS/gui/init.h"
#include "wxJS/gui/control/panel.h"
#include "wxJS/gui/misc/bitmap.h"
#include "wxJS/gui/event/jsevent.h"
#include "wxJS/gui/event/key.h"
#include "wxJS/gui/event/mouse.h"
#include "GameInterface/Shareable.h"
#include "GameInterface/Messages.h"
@ -310,31 +300,6 @@ namespace
}
};
////////////////////////////////////////////////////////////////
// wxJS types:
template<> struct ToJSVal<wxKeyEvent>
{
static jsval Convert(JSContext* cx, const wxKeyEvent& val)
{
wxKeyEvent& evt = const_cast<wxKeyEvent&>(val); // ugly, but needed for wxJS
wxjs::gui::PrivKeyEvent *jsEvent = new wxjs::gui::PrivKeyEvent(evt);
jsEvent->SetScoop(false); // (wxJS will clone the event now, and not modify the const version)
return wxjs::gui::KeyEvent::CreateObject(cx, jsEvent);
}
};
template<> struct ToJSVal<wxMouseEvent>
{
static jsval Convert(JSContext* cx, const wxMouseEvent& val)
{
wxMouseEvent& evt = const_cast<wxMouseEvent&>(val); // see comments above for KeyEvent
wxjs::gui::PrivMouseEvent *jsEvent = new wxjs::gui::PrivMouseEvent(evt);
jsEvent->SetScoop(false);
return wxjs::gui::MouseEvent::CreateObject(cx, jsEvent);
}
};
////////////////////////////////////////////////////////////////
// Compound types:
@ -360,114 +325,6 @@ namespace
return ToJSVal<T>::Convert(cx, val._Unwrap());
}
};
////////////////////////////////////////////////////////////////
// AtlasMessage structures:
template<> struct FromJSVal<AtlasMessage::Position>
{
static bool Convert(JSContext* cx, jsval v, AtlasMessage::Position& out)
{
JSObject* obj;
if (! JS_ValueToObject(cx, v, &obj) || obj == NULL)
FAIL("Argument must be an object");
jsval val;
float x, y, z;
if (! JS_GetProperty(cx, obj, "x", &val))
FAIL("Failed to get 'x'");
if (! ScriptInterface::FromJSVal(cx, val, x))
FAIL("Failed to convert 'x'");
if (! JS_GetProperty(cx, obj, "y", &val))
FAIL("Failed to get 'y'");
if (! ScriptInterface::FromJSVal(cx, val, y))
FAIL("Failed to convert 'y'");
if (! JS_GetProperty(cx, obj, "z", &val))
FAIL("Failed to get 'z'");
if (! ScriptInterface::FromJSVal(cx, val, z))
FAIL("Failed to convert 'z'");
out = AtlasMessage::Position(x, y, z);
return true;
}
};
template<> struct ToJSVal<AtlasMessage::sTerrainGroupPreview>
{
static jsval Convert(JSContext* cx, const AtlasMessage::sTerrainGroupPreview& val)
{
JSObject* obj = JS_NewObject(cx, NULL, NULL, NULL);
if (! obj) return JSVAL_VOID;
JS_DefineProperty(cx, obj, "name", ToJSVal<std::wstring>::Convert(cx, *val.name), NULL, NULL, JSPROP_ENUMERATE);
JS_DefineProperty(cx, obj, "loaded", ToJSVal<bool>::Convert(cx, val.loaded), NULL, NULL, JSPROP_ENUMERATE);
unsigned char* buf = (unsigned char*)(malloc(val.imageData.GetSize()));
memcpy(buf, val.imageData.GetBuffer(), val.imageData.GetSize());
jsval bmp = wxjs::gui::Bitmap::CreateObject(cx, new wxBitmap (wxImage(val.imageWidth, val.imageHeight, buf)));
JS_DefineProperty(cx, obj, "imagedata", bmp, NULL, NULL, JSPROP_ENUMERATE);
return OBJECT_TO_JSVAL(obj);
}
};
template<> struct ToJSVal<AtlasMessage::sObjectsListItem>
{
static jsval Convert(JSContext* cx, const AtlasMessage::sObjectsListItem& val)
{
JSObject* obj = JS_NewObject(cx, NULL, NULL, NULL);
if (! obj) return JSVAL_VOID;
JS_DefineProperty(cx, obj, "id", ToJSVal<std::wstring>::Convert(cx, *val.id), NULL, NULL, JSPROP_ENUMERATE);
JS_DefineProperty(cx, obj, "name", ToJSVal<std::wstring>::Convert(cx, *val.name), NULL, NULL, JSPROP_ENUMERATE);
JS_DefineProperty(cx, obj, "type", ToJSVal<int>::Convert(cx, val.type), NULL, NULL, JSPROP_ENUMERATE);
return OBJECT_TO_JSVAL(obj);
}
};
template<> struct ToJSVal<AtlasMessage::sObjectSettings>
{
static jsval Convert(JSContext* cx, const AtlasMessage::sObjectSettings& val)
{
JSObject* obj = JS_NewObject(cx, NULL, NULL, NULL);
if (! obj) return JSVAL_VOID;
JS_DefineProperty(cx, obj, "player", ToJSVal<size_t>::Convert(cx, val.player), NULL, NULL, JSPROP_ENUMERATE);
JS_DefineProperty(cx, obj, "selections", ToJSVal<std::vector<std::wstring> >::Convert(cx, *val.selections), NULL, NULL, JSPROP_ENUMERATE);
JS_DefineProperty(cx, obj, "variantgroups", ToJSVal<std::vector<std::vector<std::wstring> > >::Convert(cx, *val.variantGroups), NULL, NULL, JSPROP_ENUMERATE);
return OBJECT_TO_JSVAL(obj);
}
};
template<> struct FromJSVal<AtlasMessage::sObjectSettings>
{
static bool Convert(JSContext* cx, jsval v, AtlasMessage::sObjectSettings& out)
{
JSObject* obj;
if (! JS_ValueToObject(cx, v, &obj) || obj == NULL)
FAIL("Argument must be an object");
jsval val;
int player;
if (! JS_GetProperty(cx, obj, "player", &val))
FAIL("Failed to get 'player'");
if (! ScriptInterface::FromJSVal(cx, val, player))
FAIL("Failed to convert 'player'");
out.player = player;
std::vector<std::wstring> selections;
if (! JS_GetProperty(cx, obj, "selections", &val))
FAIL("Failed to get 'selections'");
if (! ScriptInterface::FromJSVal(cx, val, selections))
FAIL("Failed to convert 'selections'");
out.selections = selections;
// variantgroups is only used in engine-to-editor, so we don't
// bother converting it here
return true;
}
};
}
template<typename T> bool ScriptInterface::FromJSVal(JSContext* cx, jsval v, T& out)
@ -616,11 +473,6 @@ AtlasScriptInterface_impl::AtlasScriptInterface_impl()
JS_DefineProperty(m_cx, m_glob, "global", OBJECT_TO_JSVAL(m_glob), NULL, NULL, JSPROP_ENUMERATE|JSPROP_READONLY|JSPROP_PERMANENT);
wxjs::gui::InitClass(m_cx, m_glob);
wxjs::io::InitClass(m_cx, m_glob);
wxjs::ext::InitClass(m_cx, m_glob);
wxjs::ext::InitObject(m_cx, m_glob);
JS_DefineFunction(m_cx, m_glob, "print", ::print, 0, JSPROP_ENUMERATE|JSPROP_READONLY|JSPROP_PERMANENT);
m_atlas = JS_DefineObject(m_cx, m_glob, "Atlas", NULL, NULL, JSPROP_ENUMERATE|JSPROP_READONLY|JSPROP_PERMANENT);
@ -765,51 +617,6 @@ void ScriptInterface::LoadScript(const wxString& filename, const wxString& code)
m->LoadScript(m->m_cx, reinterpret_cast<jschar*>(codeUTF16.data()), (uintN)(codeLength/2), filename.ToAscii(), &rval);
}
wxPanel* ScriptInterface::LoadScriptAsPanel(const wxString& name, wxWindow* parent)
{
wxPanel* panel = new wxPanel(parent, -1);
JSObject* jsWindow = JSVAL_TO_OBJECT(wxjs::gui::Panel::CreateObject(m->m_cx, panel));
panel->SetClientObject(new wxjs::JavaScriptClientData(m->m_cx, jsWindow, true, false));
jsval jsName = ToJSVal(m->m_cx, name);
const uintN argc = 2;
jsval argv[argc] = { jsName, OBJECT_TO_JSVAL(jsWindow) };
jsval rval;
JS_CallFunctionName(m->m_cx, m->m_glob, "loadScript", argc, argv, &rval); // TODO: error checking
return panel;
}
// TODO: this is an ugly function to provide
std::pair<wxPanel*, wxPanel*> ScriptInterface::LoadScriptAsSidebar(const wxString& name, wxWindow* side, wxWindow* bottom)
{
wxPanel* sidePanel = new wxPanel(side, -1);
JSObject* jsSideWindow = JSVAL_TO_OBJECT(wxjs::gui::Panel::CreateObject(m->m_cx, sidePanel));
sidePanel->SetClientObject(new wxjs::JavaScriptClientData(m->m_cx, jsSideWindow, true, false));
wxPanel* bottomPanel = new wxPanel(bottom, -1);
JSObject* jsBottomWindow = JSVAL_TO_OBJECT(wxjs::gui::Panel::CreateObject(m->m_cx, bottomPanel));
bottomPanel->SetClientObject(new wxjs::JavaScriptClientData(m->m_cx, jsBottomWindow, true, false));
jsval jsName = ToJSVal(m->m_cx, name);
const uintN argc = 3;
jsval argv[argc] = { jsName, OBJECT_TO_JSVAL(jsSideWindow), OBJECT_TO_JSVAL(jsBottomWindow) };
jsval rval;
JS_CallFunctionName(m->m_cx, m->m_glob, "loadScript", argc, argv, &rval); // TODO: error checking
// TODO: This really need a better way to handle these two windows (of which one is optional)...
if (bottomPanel->GetChildren().size() != 0)
return std::make_pair(sidePanel, bottomPanel);
else
{
bottomPanel->Destroy();
return std::make_pair(sidePanel, static_cast<wxPanel*>(NULL));
}
}
////////////////////////////////////////////////////////////////
#define TYPE(elem) BOOST_PP_TUPLE_ELEM(2, 0, elem)

View File

@ -33,9 +33,7 @@
#include "js/jsapi.h"
class wxWindow;
class wxString;
class wxPanel;
namespace AtlasMessage { struct mWorldCommand; }
typedef void (*SubmitCommand)(AtlasMessage::mWorldCommand* command);
@ -68,8 +66,6 @@ public:
// in ScriptInterface.cpp, else you'll end up with linker errors.)
void LoadScript(const wxString& filename, const wxString& code);
wxPanel* LoadScriptAsPanel(const wxString& name, wxWindow* parent);
std::pair<wxPanel*, wxPanel*> LoadScriptAsSidebar(const wxString& name, wxWindow* side, wxWindow* bottom);
// Convert a jsval to a C++ type. (This might trigger GC.)
template <typename T> static bool FromJSVal(JSContext* cx, jsval val, T& ret);

View File

@ -350,42 +350,6 @@ END_EVENT_TABLE()
static AtlasWindowCommandProc g_CommandProc;
AtlasWindowCommandProc& ScenarioEditor::GetCommandProc() { return g_CommandProc; }
namespace
{
// Wrapper functions for scripts
void SetCurrentTool_(void* cbdata, wxString name)
{
static_cast<ScenarioEditor*>(cbdata)->GetToolManager().SetCurrentTool(name);
}
void SetCurrentToolWith(void* cbdata, wxString name, wxString arg)
{
static_cast<ScenarioEditor*>(cbdata)->GetToolManager().SetCurrentTool(name, &arg);
}
void SetCurrentToolWithVal(void* cbdata, wxString name, CScriptVal arg)
{
jsval tool = arg.get();
static_cast<ScenarioEditor*>(cbdata)->GetToolManager().SetCurrentTool(name, &tool);
}
wxString GetDataDirectory(void*)
{
return Datafile::GetDataDirectory();
}
// TODO: see comment in terrain.js, and remove this when/if it's no longer necessary
void SetBrushStrength(void*, float strength)
{
g_Brush_Elevation.SetStrength(strength);
}
void SetSelectedTexture(void*, wxString name)
{
g_SelectedTexture = name;
}
}
ScenarioEditor::ScenarioEditor(wxWindow* parent, ScriptInterface& scriptInterface)
: wxFrame(parent, wxID_ANY, _T(""), wxDefaultPosition, wxSize(1024, 768))
, m_FileHistory(_T("Scenario Editor")), m_ScriptInterface(scriptInterface)
@ -413,53 +377,6 @@ ScenarioEditor::ScenarioEditor(wxWindow* parent, ScriptInterface& scriptInterfac
wxImage::AddHandler(new wxPNGHandler);
//////////////////////////////////////////////////////////////////////////
// Script interface functions
GetScriptInterface().SetCallbackData(static_cast<void*>(this));
GetScriptInterface().RegisterFunction<wxString, GetDataDirectory>("GetDataDirectory");
GetScriptInterface().RegisterFunction<void, wxString, SetCurrentTool_>("SetCurrentTool");
GetScriptInterface().RegisterFunction<void, wxString, wxString, SetCurrentToolWith>("SetCurrentToolWith");
GetScriptInterface().RegisterFunction<void, wxString, CScriptVal, SetCurrentToolWithVal>("SetCurrentToolWithVal");
GetScriptInterface().RegisterFunction<void, float, SetBrushStrength>("SetBrushStrength");
GetScriptInterface().RegisterFunction<void, wxString, SetSelectedTexture>("SetSelectedTexture");
{
const wxString relativePath (_T("tools/atlas/scripts/main.js"));
wxFileName filename (relativePath, wxPATH_UNIX);
filename.MakeAbsolute(Datafile::GetDataDirectory());
wxFFile file (filename.GetFullPath());
wxString script;
if (! file.ReadAll(&script))
{
wxLogError(_("Failed to read script"));
}
GetScriptInterface().LoadScript(filename.GetFullName(), script);
}
// Load common scripts
const wxString commonPath(_T("tools/atlas/scripts/common/"));
wxFileName filename(commonPath, wxPATH_UNIX);
filename.MakeAbsolute(Datafile::GetDataDirectory());
wxArrayString filenames;
if (wxDir::GetAllFiles(filename.GetFullPath(), &filenames, _T("*.js")) > 0)
{
for (size_t i = 0; i < filenames.GetCount(); ++i)
{
wxFFile file (filenames[i]);
wxString script;
if (! file.ReadAll(&script))
{
wxLogError(_("Failed to read script"));
}
GetScriptInterface().LoadScript(filename.GetFullName(), script);
}
}
else
{
wxLogError(_("Failed to read common scripts directory"));
}
//////////////////////////////////////////////////////////////////////////
// Do some early game initialisation:

View File

@ -248,29 +248,6 @@ void SidebarButton::OnClick(wxCommandEvent& WXUNUSED(event))
//////////////////////////////////////////////////////////////////////////
class ScriptedSidebar : public Sidebar
{
public:
ScriptedSidebar(const wxString& name, ScenarioEditor& scenarioEditor, wxWindow* sidebarContainer, wxWindow* bottomBarContainer)
: Sidebar(scenarioEditor, sidebarContainer, bottomBarContainer), m_BottomBarContainer(bottomBarContainer), m_Name(name)
{
}
virtual void OnFirstDisplay()
{
Freeze();
std::pair<wxPanel*, wxPanel*> panels = m_ScenarioEditor.GetScriptInterface().LoadScriptAsSidebar(_T("section/") + m_Name, this, m_BottomBarContainer);
m_MainSizer->Add(panels.first, wxSizerFlags(1).Expand());
m_BottomBar = panels.second;
Layout();
Thaw();
}
private:
wxString m_Name;
wxWindow* m_BottomBarContainer;
};
SectionLayout::SectionLayout()
{
}
@ -310,13 +287,6 @@ void SectionLayout::Build(ScenarioEditor& scenarioEditor)
m_SidebarBook->AddPage(sidebar, icon, tooltip); \
m_PageMappings.insert(std::make_pair(L###classname, (int)m_SidebarBook->GetPageCount()-1));
#define ADD_SIDEBAR_SCRIPT(name, icon, tooltip) \
sidebar = new ScriptedSidebar(name, scenarioEditor, m_SidebarBook->GetContentWindow(), m_VertSplitter); \
if (sidebar->GetBottomBar()) \
sidebar->GetBottomBar()->Show(false); \
m_SidebarBook->AddPage(sidebar, icon, tooltip); \
m_PageMappings.insert(std::make_pair(name, (int)m_SidebarBook->GetPageCount()-1));
ADD_SIDEBAR(MapSidebar, _T("map.png"), _("Map"));
ADD_SIDEBAR(TerrainSidebar, _T("terrain.png"), _("Terrain"));
ADD_SIDEBAR(ObjectSidebar, _T("object.png"), _("Object"));

View File

@ -1,96 +0,0 @@
/* Copyright (C) 2009 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* 0 A.D. is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
*/
#include "precompiled.h"
#include "ScenarioEditor/ScenarioEditor.h"
#include "AtlasScript/ScriptInterface.h"
class ScriptedTool : public StateDrivenTool<ScriptedTool>
{
DECLARE_DYNAMIC_CLASS(ScriptedTool);
jsval m_Tool;
ScriptInterface* m_ScriptInterface;
public:
ScriptedTool()
{
}
virtual void Init(void* initData, ScenarioEditor* scenarioEditor)
{
StateDrivenTool<ScriptedTool>::Init(initData, scenarioEditor);
m_ScriptInterface = &scenarioEditor->GetScriptInterface();
wxASSERT(initData);
jsval& tool = *static_cast<jsval*>(initData);
m_Tool = tool;
m_ScriptInterface->AddRoot(&m_Tool);
SetState(&Running);
}
virtual void Shutdown()
{
m_ScriptInterface->RemoveRoot(&m_Tool);
StateDrivenTool<ScriptedTool>::Shutdown();
}
void OnEnable()
{
m_ScriptInterface->CallFunction(m_Tool, "onEnable");
}
void OnDisable()
{
m_ScriptInterface->CallFunction(m_Tool, "onDisable");
}
struct sRunning : public State
{
bool OnMouse(ScriptedTool* obj, wxMouseEvent& evt)
{
bool ret;
if (! obj->m_ScriptInterface->CallFunction(obj->m_Tool, "onMouse", evt, ret))
return false;
return ret;
}
bool OnKey(ScriptedTool* obj, wxKeyEvent& evt, KeyEventType type)
{
wxString typeStr;
switch (type) {
case KEY_DOWN: typeStr = _T("down"); break;
case KEY_UP: typeStr = _T("up"); break;
case KEY_CHAR: typeStr = _T("char"); break;
}
bool ret;
if (! obj->m_ScriptInterface->CallFunction(obj->m_Tool, "onKey", evt, typeStr, ret))
return false;
return ret;
}
void OnTick(ScriptedTool* obj, float dt)
{
bool ret;
obj->m_ScriptInterface->CallFunction(obj->m_Tool, "onTick", dt, ret);
}
}
Running;
};
IMPLEMENT_DYNAMIC_CLASS(ScriptedTool, StateDrivenTool<ScriptedTool>);