From 26a100156112f0772c3e6f987ba0db927922dac6 Mon Sep 17 00:00:00 2001 From: ChapelR Date: Tue, 15 May 2018 04:10:34 -0400 Subject: [PATCH] docs update, minor API improvements --- docs/2-Installation.md | 12 +- docs/7-JavaScript-API.md | 402 ++++++++++++++++++++++++++++++++++++++- docs/8-CSS-Reference.md | 31 ++- readme.md | 6 +- src/js/layout.js | 13 +- src/js/z-character.js | 2 +- 6 files changed, 451 insertions(+), 15 deletions(-) diff --git a/docs/2-Installation.md b/docs/2-Installation.md index 1f02189..d68d006 100644 --- a/docs/2-Installation.md +++ b/docs/2-Installation.md @@ -2,7 +2,17 @@ ### Part 1: Get the files. -Download the files, or grab the `dist/` directory of this repo. You need the `cac` folder with all it's images, and the `noble.min.css` and `noble.min.js` files. You can also download an html version of the documentation from [coming soon] or [coming soon]. +Download the files, or grab the `dist/` directory of this repo. You need the `cac` folder with all it's images, and the `noble.min.css` and `noble.min.js` files. You can also download an html version of the documentation for offline use. + +Download the files: +* [From Google Drive](https://drive.google.com/open?id=1rCXShwoD3teElwwgheosZyYeUREfjtnB) +* [From GitHub](https://github.com/ChapelR/holy-land-demo/raw/master/noble-avatar/noble-avatars.zip) +* [From HolyLandGame.com](http://holylandgame.com/noble-avatar/noble-avatars.zip) + +Download the docs: +* [From Google Drive](https://drive.google.com/open?id=1U27wuSrZjXOr1-Jcu5clgqKEM2aYsddr) +* [From GitHub](https://github.com/ChapelR/holy-land-demo/raw/master/noble-avatar/noble-avatars.docs.zip) +* [From HolyLandGame.com](http://holylandgame.com/noble-avatar/noble-avatars.docs.zip) ### Part 2: Place the `cac` folder. diff --git a/docs/7-JavaScript-API.md b/docs/7-JavaScript-API.md index 982f06c..125f10f 100644 --- a/docs/7-JavaScript-API.md +++ b/docs/7-JavaScript-API.md @@ -1,3 +1,403 @@ ## JavaScript API -*Coming soon.* \ No newline at end of file +All of the JavaScript used by this system is part of the global `window.Noble` namespace. + +## `Noble.config` + +See the [configuration options](4-Config.md). + +## `Noble.components` + +This object stores all of the relative URLs for each of the items. It's structured like this: + +```javascript +Noble.components = { + [groupName] : { + components : { + u : [ arrayOfItems ], + f : [ arrayOfItems ], + m : [ arrayOfItems ] + }, + required : [ boolean ], + dir : { + u : [ pathToFolder ], + f : [ pathToFolder ], + m : [ pathToFolder ] + } + }, + [etc...] +} +``` + +Each group name represents a single slot on the character, like hair, mouths, eyes, etc. In the `components` object, tree arrays of file names are stored--one for unisex items (`u`), one for female items (`f`), and one for male items (`m`). The `required` boolean value simply lets the system know 1) not to generate a random portrait without something in this slot, and 2) not to give the player the option to have nothing in this slot in the editor. Theoretically, you could edit this option to make anything required or not required for any group. + +If you want to use your own custom components, you'll need to spend some time editing this object, or rebuilding it. Check out the [guide](9-Customization.md) for more. + +## `Noble.slots` + +This is the API you can use to generate custom and random characters. It's geared toward making characters at run-time; there are two "base" character objects, one for male and one for female. To make a character, you can equip items to their slots, then send the appropriate male or female object to `Noble.Character` to finish it up. + +### The male and female slots objects + +The male and female objects have the following structures: +```javascript +Noble.slots = { + [gender] : { + [groupName] : { + has : [ boolean ], + component : [ currentComponent ], + options : [ arrayOfPossibleComponents ] + }, + [etc...] + }, [otherGender] : { + [etc...] + } +} +``` + +Like with components, each `groupName` represents a single item slot; eyes, mouth, hair, etc. The `has` property determines whether a character can equip something in that slot (for example, females can't have beards, so `Noble.slots.female.beard.has === false`). + +### Methods + +The `Noble.slots` object has the following methods. + +#### `Noble.slots.check.required(groupName)` + +Returns whether the passed `groupName` is required. + +Returns: boolean + +Arguments: +* groupName (string): The group name. + +Examples: +```javascript +Noble.slots.check.required('hair'); // false +Noble.slots.check.required('eyes'); // true +``` + +#### `Noble.slots.check.possible(groupName, gender)` + +Returns whether the passed gender can have a component from the group. + +Returns: boolean + +Arguments: +* groupName (string): The group name. +* gender (string): `'male'` or `'female'`. + +Examples: +```javascript +Noble.slots.check.possible('hair', 'male'); // true +Noble.slots.check.possible('beard', 'female'); // false +``` + +#### `Noble.slots.set(groupName, gender, component)` + +This method places or replaces a given component on the relevant slots object. + +Returns: false if the equip is impossible, otherwise the component URL. + +Arguments: +* groupName (string): The group name. +* gender (string): `'male'` or `'female'`. +* component (string): the URL to an image asset of a component. + +Examples: +```javascript +Noble.slots.set('hair', 'female', './cac/hair/f/hair_f5.png'); +``` + +#### `Noble.slots.unset(groupName, gender)` + +This method replaces the component value with an empty string for the gender object indicated. + +Returns: the URL of the item that was equipped before this method was run. + +Arguments: +* groupName (string): The group name. +* gender (string): `'male'` or `'female'`. + +Examples: +```javascript +Noble.slots.unset('hair', 'female'); +``` + +#### `Noble.slots.randomize(groupName, gender)` + +This method assigns a random component URL from the list of possible options to the group indicated for the gender indicated. If the item is not required, it has a chance to be set to empty as well. + +Returns: the URL of the item that was equipped. + +Arguments: +* groupName (string): The group name. +* gender (string): `'male'` or `'female'`. + +Examples: +```javascript +Noble.slots.randomize('hair', 'female'); +``` + +#### `Noble.slots.randomizeAll(gender)` + +Takes the indicated gender object and randomizes all it's slots. Useful for generating random characters. + +Returns: undefined + +Arguments: +* gender (string): `'male'` or `'female'`. + +Examples: +```javascript +Noble.slots.randomizeAll('female'); +``` + +#### `Noble.slots.convert(slotsObj)` + +When you pass a slots object or a clone of one to this method, it trims the unnecessary data to create a definition object for the `Noble.Character` API. + +Returns: a definition object. + +Arguments: +* slotsObj: a gender object or clone of one. + +Examples: +```javascript +var ch = Noble.slots.convert(Noble.slots.female); +new Noble.Character('sally', ch); +``` + +## `Noble.Character` + +`Noble.Character` is a constructor function for making character instances. In most cases, however, you'll want to call `Noble.Character.add()` to make your character instances, as this function will add the necessary plumbing to make your character available to the system without needing to assign it to a variable. + +Instances of `Noble.Character` have the following properties. +* `.id`: the id of the avatar. +* `.def`: the definition object; a series of key value pairs where each key is group and each value is the corresponding component URL (or an empty string). + +### Static Methods + +#### `Noble.Character.add(id, definitionOrSlotsObj)` + +This method creates a new `Noble.Character` instance and pushed it into the story variable array (see [the configuration options](4-Config.md)). It will also automatically convert slots objects to definition objects via `Noble.slots.convert` when needed. + +Returns: a new Noble.Character instance. + +Arguments: +* id (string): the avatar ID to assign to the character instance. +* definitionOrSlotsObj (object): a definition object or a slots object. If a slots object is passed, `Noble.slots.convert()` will be called on it automatically. + +Example: +```javascript +Noble.Character.add('sally', Noble.slots.female); +``` + +#### `Noble.Character.is(thing)` + +Returns whether the passed object, value, or variable is an instance of `Noble.Character`. + +Returns: boolean + +Arguments: +* thing (any): anything. + +Example: +```javascript +var obj = {}; +var that = 'hello'; +var ch = Noble.Character.add('blah', Noble.slots.male); + +Noble.Character.is(obj); // false +Noble.Character.is(that); // false +Noble.Character.is('blah'); // false +Noble.Character.is(Noble.slots.male); // false +Noble.Character.is(ch); // true +``` + +#### `Noble.Character.generateFromPassage(passageName)` + +Attempts to pull avatar data from the indicated passage. If it is a valid [avatar passage](6-Avatar-Passage.md), a new `Noble.Character` instance is created, and the passage's name is used as the id. + +Returns: `undefined` + +Arguments: +* passageName (string): the name of a passage. + +Example: +```javascript +Noble.Character.generateFromPassage('my avatar passage'); +``` + +#### `Noble.Character.getByID(id)` + +Searches the story variable array for the `Noble.Character` instance with the given id. + +Returns: A `Noble.Character` instance or `undefined`. + +Arguments: +* id (string): the id of a `Noble.Character` instance. + +Example: +```javascript +var ch = Noble.Character.getByID('sally'); +``` + +#### `Noble.Character.random(id [, gender])` + +This method creates a new `Noble.Character` instance, but randomizes all the components. You can choose to supply a gender. + +Coming soon: In a future update, I'd like for this object to also accept any parameters the player wishes while randomizing the rest. + +Returns: A new `Noble.Character` instance. + +Arguments: +* id (string): the id to assign to the new instance +* gender (string) (optional): `'male'` or `'female'` + +Example: +```javascript +var ch = Noble.Character.getByID('sally'); +``` + +### Instance methods + +#### `.portrait()` + +This method takes the `Noble.Character` instance and generates and returns a `Noble.Portrait` object from it. You should always use this method when possible, rather than the `Noble.Portrait` constructor. + +Returns: a new `Noble.Portrait` instance generated from the `Noble.Character` instance. + +Example: +```javascript +var chSally = Noble.Character.add('sally', Noble.slots.female); +var ptSally = chSally.portrait(); + +// place sally's portrait on the page: +ptSally.$el.appendTo('#passages'); +``` + +#### `.clickablePt([wikiCode])` + +This method is similar to the above, but generates a clickable portrait. The provided wiki code is run on click. + +Returns: a new, clickable `Noble.Portrait` instance generated from the `Noble.Character` instance. + +Arguments: +* wikiCode (string): a string of valid TwineScript code. + +Example: +```javascript +var chSally = Noble.Character.add('sally', Noble.slots.female); +var ptSally = chSally.clickablePt('<>'); + +// place sally's portrait on the page: +ptSally.$el.appendTo('#passages'); +// when the portrait is clicked, the code will run +``` + +## `Noble.Portrait` + +`Noble.Portrait` is a constructor function that creates a complete portrait element in jQuery to be loaded onto the page. To save memory and prevent issues with SugarCube's state, these instances are not stateful and never really saved anywhere, and are usually garbage collected once they're no longer being displayed. They're created as needed. You should call the `.portrait()` method rather than using this constructor in most cases. + +Note that these objects cannot be saved as story variables, as the history system cannot track or clone them. + +Each `Noble.Portrait` instance has these properties: +* `.id`: the id of the `Noble.Character` instance the portrait is for. +* `.$el`: the entire, constructed portrait element, in a jQuery wrapper. +* `.$layers`: an array of references to the jQuery elements making up each layer of the image. +* `.wiki`: any wiki code that should be run on click, or `undefined`. + +### Instance Methods + +#### `.getLayer(groupName)` + +This method returns the jQuery element from the `.$layers` array that corresponds to the component group requested, or undefined, if it cannot be found. + +Returns: a jQuery element or `undefined`. + +Arguments: +* groupName (string): the name of a component group. + +#### `.getLayerIdx(groupName)` + +As above, but this method returns the index of the element in the `.$layers` array, rather than a reference to the element itself. + +Returns: integer (array index or -1) + +Arguments: +* groupName (string): the name of a component group. + +#### `.changeLayer(groupName, component)` + +This layer gets the indicated jQuery layer element and changes its background image to the provided component URL. This does not alter or effect the underlying `Noble.Character` instance, only the visuals of the portrait element. + +Returns: `undefined` + +Arguments: +* groupName (string): the name of a component group. +* component (string): the component URL to change the layer's image to. + +## `Noble.editor` + +The `Noble.editor` interface controls the avatar editor. There's no way to make this API not complicated; users who want to dramatically alter the editor and its functionality are better off looking at the source code. As such, this section will be brief and light on details and examples. + +### Properties + +This interface has a few properties that may be of use to authors: + +* `Noble.editor.gender` (string): the currently selected gender. +* `Noble.editor.madeChanges['male'|'female']` (boolean): records whether the player has altered the avatars at all. + +### Methods + +#### `Noble.editor.start(target, id, passageName [, debug])` + +Starts up the editor and appends it to the target element. This is used for the macro, but it requires passage transition to work properly. If you need to call the editor as some other time, you can rebuild it using the other methods below. + +Returns: `undefined` + +Arguments: +* target (string): a jQuery-style selector to append the editor to. +* id (string): the id of the avatar being created. +* passageName (string): the name of the passage to navigate to when the player confirms their creation. +* debug (boolean) (optional): providing a truthy argument starts the editor in debug mode, meaning clicking the portrait in the editor will display the avatar's JSON data for use in an [avatar passage](6-Avatar-Passages.md). + +#### `Noble.editor.update()` + +This method updates the editor's entire display, and is used when the player swaps genders. + +Returns: `undefined` + +#### `Noble.editor.content()` + +This method updates the editor's content window. Only used on initialization or when gender is switched. + +#### `Noble.editor.portrait()` + +This method updates the player's portrait when a component is selected. + +Returns: a `Noble.Portrait` instance + +#### `Noble.editor.confirmBtn($el, id, passageName)` + +This method creates and appends the confirm button on the editor. + +Arguments: +* $el (jQuery object): the jQuery object to attach the button to; generally the editor. +* id (string): the id of the avatar being created. +* passageName (string): the name of the passage to navigate to when the player confirms their creation. + +#### `Noble.editor.build()` + +Creates the editor interface and returns it as a jQuery element. + +Returns: a jQuery element referencing the editor. + +#### `Noble.editor.handlers([debug])` + +Attaches event handlers to all of the editor elements. Best called after everything else has been built. + +Returns: `undefined` + +Arguments: +* debug (boolean) (optional): if truthy, adds the debug handlers. diff --git a/docs/8-CSS-Reference.md b/docs/8-CSS-Reference.md index 7525411..c2a380c 100644 --- a/docs/8-CSS-Reference.md +++ b/docs/8-CSS-Reference.md @@ -1,14 +1,11 @@ ## CSS Selectors Reference -* [Portrait](#portrait-css) -* [Editor](#the-editor) - ### Portrait CSS `div.noble-wrapper` is the container element onto which the png layers of each image are layered. To change the size or position of the image, you'll want to use this selector. Each portrait further has a number of individual layers, each one uses the `div.noble-wrapper div.layer` selector. The images are laid in order, meaning we don't use z-index to order them. In general, there should be any reason to mess with the layers as doing so could cause them to fail to lay properly. The basic portrait CSS looks like this: -``` +```css div.noble-wrapper { position: relative; width: 400px; @@ -26,7 +23,7 @@ div.noble-wrapper div.layer { Additionally, the portraits accept various options, which are each converted to classes by the `<>` and `<>` macros. These classes have the following CSS: -``` +```css /* floats */ div.noble-wrapper.right { float: right; @@ -116,7 +113,7 @@ div.noble-wrapper.relative.very-large { ### The Editor The avatar editor's HTML structure looks like this: -``` +```html
@@ -154,7 +151,7 @@ The avatar editor's HTML structure looks like this: And the editor's default CSS: -``` +```css div#editor-view { width: 49%; height: 250px; @@ -191,4 +188,24 @@ button#editor-button-confirm { width: 99%; margin: 2em 0; } +``` + +### Responsive Rules + +The following CSS adds a bit of responsiveness to the editor: +```css +@media only screen and (max-width: 600px) { + div#editor-view { + width: 100%; + margin: 1em 0; + } + div#editor-view div.noble-wrapper { + height: 100%; + width: unset; + margin: auto; + } + div#editor-window-wrapper { + width: 100%; + } +} ``` \ No newline at end of file diff --git a/readme.md b/readme.md index fabea9a..885da45 100644 --- a/readme.md +++ b/readme.md @@ -39,10 +39,10 @@ Noble avatars is a drop-in character portrait generator for the SugarCube 2 stor * Unfortunately, Noble Avatars uses totally different assets for the base male and female options, meaning that gender selection is completely binary and required. * Right now, there's no way to tag certain creation options (outside gender restrictions and required-ness, i.e. all characters require eyes), meaning character portraits that are generated randomly are completely random by default, though you can use the API to supply only certain options to certain randomized characters, but this is labor-intensive. -## Legal info +## Licensing info This code is licensed under MIT. See the license for more. In general, you must provide attribution to me (Chapel) in addition to including the info from the credits section somewhere in your game, like an about page. It does not need to be particularly prominent. Please avoid implying that any of the individuals, myself included, directly worked on or endorsed your project. ## Credits -[Avatar graphics created by Noble Master Games](http://www.noblemaster.com) -[Avatar graphics designed by Mei-Li Nieuwland](http://liea.deviantart.com) +[Avatar graphics created by Noble Master Games](http://www.noblemaster.com) +[Avatar graphics designed by Mei-Li Nieuwland](http://liea.deviantart.com) Noble Avatar Graphics licensed under [CC-BY-3.0](https://creativecommons.org/licenses/by/3.0/legalcode) \ No newline at end of file diff --git a/src/js/layout.js b/src/js/layout.js index 5fcee04..722d2aa 100644 --- a/src/js/layout.js +++ b/src/js/layout.js @@ -59,12 +59,20 @@ .attr('id', 'editor-button-confirm') .wiki(confirmText()) .ariaClick( function () { + $(document).trigger({ type : ':editor-confirm', id : id, passage : psg }); + + Noble.editor.madeChanges = { + male : false, + female : false + } + $(this).remove(); + }).appendTo($el); } @@ -138,14 +146,14 @@ $('div#editor-window button#gender').ariaClick( function () { - $(this).empty().wiki(swapGenderText(Noble.editor.gender)); - if (Noble.editor.gender === 'female') { Noble.editor.gender = 'male'; } else { Noble.editor.gender = 'female'; } + $(this).empty().wiki(swapGenderText(Noble.editor.gender)); + updateEditor(); }); @@ -201,6 +209,7 @@ Noble.editor.update = updateEditor; Noble.editor.content = populateEditor; Noble.editor.portrait = updatePt; + Noble.editor.confirmBtn = createConfirmBtn; Noble.editor.build = buildEditor; Noble.editor.handlers = addHandlers; diff --git a/src/js/z-character.js b/src/js/z-character.js index 2a54482..0b4ee2c 100644 --- a/src/js/z-character.js +++ b/src/js/z-character.js @@ -42,7 +42,7 @@ }); }; - Noble.Character.random = function (gender, id) { + Noble.Character.random = function (id, gender) { gender = gender || either('male', 'female'); id = id || 'rnd-' + Math.random().toString(36).substring(7); Noble.slots.randomizeAll(gender);