-
Notifications
You must be signed in to change notification settings - Fork 67
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
add avatars functionality #351
base: dev
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,113 @@ | ||||||
avatar | ||||||
====== | ||||||
|
||||||
Renders an avatar SVG image using using https://avatars.dicebear.com/. Uses the SVG-specified units and DPI to determine the pixel width and height. If neither data nor file are specified for a given card, this method does nothing. | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Need to document that it'll save a file and only download if it's not saved already |
||||||
|
||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should also probably say that beyond the first few options, it's identical to |
||||||
|
||||||
Options | ||||||
------- | ||||||
.. include:: /args/expansion.rst | ||||||
|
||||||
library | ||||||
default: ``'avataaars'`` | ||||||
|
||||||
avatar library to use. Options are ``'male'``, ``'female'``, ``'human'``, ``'identicon'``, ``'initials'``, ``'bottts'``, ``'avataaars'``, ``'jdenticon'``, ``'gridy'`` or ``'micah'``. | ||||||
|
||||||
.. include:: /args/xy.rst | ||||||
|
||||||
seed | ||||||
default: ``nil`` | ||||||
|
||||||
string to use as the randomizer for the avatar library. Or, in the case of ``'initials'``, the actual initials shown in the returned image. | ||||||
|
||||||
width | ||||||
default: ``native`` | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
|
||||||
the pixel width that the image should scale to. Setting this to ``:deck`` will scale to the deck height. ``:scale`` will use the width to scale and keep native the aspect ratio. SVG scaling is done with vectors, so the scaling should be smooth. When set to ``:native``, uses the DPI and units of the loaded SVG document. Supports :doc:`/units` and :doc:`/shorthands`. | ||||||
|
||||||
height | ||||||
default: ``:native`` | ||||||
|
||||||
the pixel width that the image should scale to. ``:deck`` will scale to the deck height. ``:scale`` will use the width to scale and keep native the aspect ratio. SVG scaling is done with vectors, so the scaling should be smooth. When set to ``:native``, uses the DPI and units of the loaded SVG document. Supports :doc:`/units` and :doc:`/shorthands`. | ||||||
|
||||||
blend | ||||||
default: ``:none`` | ||||||
|
||||||
the composite blend operator used when applying this image. See Blend Modes at http://cairographics.org/operators. | ||||||
The possibilties include ``:none``, ``:multiply``, ``:screen``, ``:overlay``, ``:darken``, ``:lighten``, ``:color_dodge``, ``:color_burn``, ``:hard_light``, ``:soft_light``, ``:difference``, ``:exclusion``, ``:hsl_hue``, ``:hsl_saturation``, ``:hsl_color``, ``:hsl_luminosity``. String versions of these options are accepted too. | ||||||
|
||||||
angle | ||||||
default: ``0`` | ||||||
|
||||||
rotation of the image in radians. Note that this rotates around the upper-left corner, making the placement of x-y coordinates slightly tricky. | ||||||
|
||||||
mask | ||||||
default: ``nil`` | ||||||
|
||||||
if specified, the image will be used as a mask for the given color/gradient. Transparent pixels are ignored, opaque pixels are the given color. Note: the origin for gradient coordinates is at the given x,y, not at 0,0 as it is most other places. | ||||||
|
||||||
.. warning:: | ||||||
|
||||||
For implementation reasons, your vector image will be rasterized when mask is applied. If you use this with, say, PDF, the images will be embedded as rasters, not vectors. | ||||||
|
||||||
crop_x | ||||||
default: ``0`` | ||||||
|
||||||
crop the loaded image at this x coordinate. Supports :doc:`/units` | ||||||
|
||||||
crop_y | ||||||
default: ``0`` | ||||||
|
||||||
crop the loaded image at this y coordinate. Supports :doc:`/units` | ||||||
|
||||||
crop_corner_radius | ||||||
default: ``0`` | ||||||
|
||||||
Radius for rounded corners, both x and y. When set, overrides crop_corner_x_radius and crop_corner_y_radius. Supports :doc:`/units` | ||||||
|
||||||
crop_corner_x_radius | ||||||
default: ``0`` | ||||||
|
||||||
x radius for rounded corners of cropped image. Supports :doc:`/units` | ||||||
|
||||||
crop_corner_y_radius | ||||||
default: ``0`` | ||||||
|
||||||
y radius for rounded corners of cropped image. Supports :doc:`/units` | ||||||
|
||||||
crop_width | ||||||
default: ``0`` | ||||||
|
||||||
width of the cropped image. Supports :doc:`/units` | ||||||
|
||||||
crop_height | ||||||
default: ``0`` | ||||||
|
||||||
ive): Height of the cropped image. Supports :doc:`/units` | ||||||
|
||||||
flip_horizontal | ||||||
default: ``false`` | ||||||
|
||||||
Flip this image about its center horizontally (i.e. left becomes right and vice versa). | ||||||
|
||||||
flip_vertical | ||||||
default: ``false`` | ||||||
|
||||||
Flip this image about its center verticall (i.e. top becomes bottom and vice versa). | ||||||
|
||||||
.. include:: /args/range.rst | ||||||
.. include:: /args/layout.rst | ||||||
|
||||||
|
||||||
Examples | ||||||
-------- | ||||||
|
||||||
These examples live here: https://github.com/andymeneely/squib/tree/dev/samples/avatars | ||||||
|
||||||
.. literalinclude:: ../../samples/avatars/_avatars.rb | ||||||
:linenos: | ||||||
|
||||||
.. raw:: html | ||||||
|
||||||
<img src="../images/_avatars_00_expected.png" width=600 class="figure"> | ||||||
|
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,92 @@ | ||||||
require 'mechanize' | ||||||
require_relative '../errors_warnings/warn_unexpected_params' | ||||||
require_relative '../args/card_range' | ||||||
require_relative '../args/paint' | ||||||
require_relative '../args/scale_box' | ||||||
require_relative '../args/transform' | ||||||
require_relative '../args/svg_special' | ||||||
|
||||||
module Squib | ||||||
class Deck | ||||||
def avatar(opts = {}) | ||||||
DSL::Avatar.new(self, __callee__).run(opts) | ||||||
end | ||||||
end | ||||||
|
||||||
module DSL | ||||||
# Add an avatar for placeholder art in your games | ||||||
# using https://avatars.dicebear.com/. The image will | ||||||
# be downloaded to your configured image directory if | ||||||
# it doesn't already exist. | ||||||
# | ||||||
# Library can be male, female, human, identicon, initials, | ||||||
# bottts, avataaars, jdenticon, gridy or micah. | ||||||
# | ||||||
# Seed can be any random string | ||||||
# | ||||||
# Example: | ||||||
# avatar library: 'micah', seed: '1234' | ||||||
class Avatar | ||||||
include WarnUnexpectedParams | ||||||
attr_reader :dsl_method, :deck | ||||||
|
||||||
def initialize(deck, dsl_method) | ||||||
@deck = deck | ||||||
@dsl_method = dsl_method | ||||||
end | ||||||
|
||||||
def self.accepted_params | ||||||
%i[ | ||||||
library seed | ||||||
x y width height | ||||||
blend mask | ||||||
crop_x crop_y crop_width crop_height | ||||||
crop_corner_radius crop_corner_x_radius crop_corner_y_radius | ||||||
flip_horizontal flip_vertical angle | ||||||
range layout | ||||||
] | ||||||
end | ||||||
|
||||||
def run(opts) | ||||||
warn_if_unexpected opts | ||||||
Dir.chdir(deck.img_dir) do | ||||||
defaults = { library: 'avataaars' } | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
I like to have everything have a default so things work even if you forget something. This seemed most sensible |
||||||
options = defaults.merge opts | ||||||
|
||||||
# Extract the default svg options | ||||||
range = Args.extract_range opts, deck | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think as it currently stands It also allows us to specify all these: https://avatars.dicebear.com/docs/options. |
||||||
svg_args = Args.extract_svg_special opts, deck | ||||||
paint = Args.extract_paint opts, deck | ||||||
box = Args.extract_scale_box opts, deck | ||||||
trans = Args.extract_transform opts, deck | ||||||
|
||||||
deck.progress_bar.start('Loading Avatar(s)', range.size) do |bar| | ||||||
range.each do |i| | ||||||
library = options[:library] | ||||||
seed = options[:seed] | ||||||
next if seed.nil? | ||||||
|
||||||
file = "avatar-#{library}-#{seed}.svg" | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we should give people control over this, similar to Something like an option called irb(main):001:0> "avatar-%s-%s.svg" % ['a','b']
=> "avatar-a-b.svg" We could also document a sample that allows you to put the avatar it is own folder: irb(main):002:0> "avatars/%s-%s.svg" % ['a','b']
=> "avatars/a-b.svg" |
||||||
|
||||||
# Check if we need to download the image | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'd like this chunk to be extracted out to a separate file - that way this class is only doing DSL method delegation stuff and we can test the dicebear thing separately. Maybe in a file like |
||||||
unless File.exist?(file) | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should wrap this in a begin/rescue so we can report a more helpful error. |
||||||
agent = Mechanize.new | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Might also be good to do a log statement whenever we download. It'll be verbose the first time, but at least people would know when it's downloading and not. |
||||||
agent.follow_meta_refresh = true | ||||||
agent.keep_alive = false | ||||||
agent.history.max_size = 10 | ||||||
|
||||||
response = agent.get_file("https://avatars.dicebear.com/api/#{library}/#{seed}.svg") | ||||||
response = response.encode('ascii-8bit').force_encoding('utf-8') | ||||||
|
||||||
File.open(file, 'w') { |f| f.write(response) } | ||||||
end | ||||||
|
||||||
deck.cards[i].svg(file, svg_args[i], box[i], paint[i], trans[i]) | ||||||
bar.increment | ||||||
end | ||||||
end | ||||||
end | ||||||
end | ||||||
end | ||||||
end | ||||||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
avatar-*.svg | ||
avatars/*.svg | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we need this second line? Would be nice if we had some samples that had already downloaded an avatar, that would be nice for regression testing reasons. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
require 'squib' | ||
require 'squib/sample_helpers' | ||
|
||
Squib::Deck.new(width: 1000, height: 2050, config: 'avatar_config.yml') do | ||
draw_graph_paper width, height | ||
|
||
sample "Avatar library - 'male'." do |x, y| | ||
avatar library: 'male', seed: 'abcde', x: x, y: y, width: 96, height: 96 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you add an example showing different avatars on different cards? |
||
avatar library: 'male', seed: 'fghij', x: x + 125, y: y, width: 96, height: 96 | ||
end | ||
|
||
sample "Avatar library - 'female'." do |x, y| | ||
avatar library: 'female', seed: 'abcde', x: x, y: y, width: 96, height: 96 | ||
avatar library: 'female', seed: 'fghij', x: x + 125, y: y, width: 96, height: 96 | ||
end | ||
|
||
sample "Avatar library - 'human'." do |x, y| | ||
avatar library: 'human', seed: 'abcde', x: x, y: y, width: 96, height: 96 | ||
avatar library: 'human', seed: 'fghij', x: x + 125, y: y, width: 96, height: 96 | ||
end | ||
|
||
sample "Avatar library - 'identicon'." do |x, y| | ||
avatar library: 'identicon', seed: 'abcde', x: x, y: y, width: 96, height: 96 | ||
avatar library: 'identicon', seed: 'fghij', x: x + 125, y: y, width: 96, height: 96 | ||
end | ||
|
||
sample "Avatar library - 'initials'." do |x, y| | ||
avatar library: 'initials', seed: 'Longer Name', x: x, y: y, width: 96, height: 96 | ||
avatar library: 'initials', seed: 'RN', x: x + 125, y: y, width: 96, height: 96 | ||
end | ||
|
||
sample "Avatar library - 'bottts'." do |x, y| | ||
avatar library: 'bottts', seed: 'abcde', x: x, y: y, width: 96, height: 96 | ||
avatar library: 'bottts', seed: 'fghij', x: x + 125, y: y, width: 96, height: 96 | ||
end | ||
|
||
sample "Avatar library - 'avataaars'." do |x, y| | ||
avatar library: 'avataaars', seed: 'abcde', x: x, y: y, width: 96, height: 96 | ||
avatar library: 'avataaars', seed: 'fghij', x: x + 125, y: y, width: 96, height: 96 | ||
end | ||
|
||
sample "Avatar library - 'jdenticon'." do |x, y| | ||
avatar library: 'jdenticon', seed: 'abcde', x: x, y: y, width: 96, height: 96 | ||
avatar library: 'jdenticon', seed: 'fghij', x: x + 125, y: y, width: 96, height: 96 | ||
end | ||
|
||
sample "Avatar library - 'gridy'." do |x, y| | ||
avatar library: 'gridy', seed: 'abcde', x: x, y: y, width: 96, height: 96 | ||
avatar library: 'gridy', seed: 'fghij', x: x + 125, y: y, width: 96, height: 96 | ||
end | ||
|
||
sample "Avatar library - 'micah'." do |x, y| | ||
avatar library: 'micah', seed: 'abcde', x: x, y: y, width: 96, height: 96 | ||
avatar library: 'micah', seed: 'fghij', x: x + 125, y: y, width: 96, height: 96 | ||
end | ||
|
||
save_png prefix: '_avatars_' | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
img_dir: '.' |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -36,6 +36,7 @@ Gem::Specification.new do |spec| | |
spec.add_runtime_dependency 'gio2', '~> 3.4' | ||
spec.add_runtime_dependency 'gobject-introspection', '~> 3.4' | ||
spec.add_runtime_dependency 'highline', '2.0.3' | ||
spec.add_runtime_dependency 'mechanize', '~> 2.7' | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Mechanize might be overkill for us - I think we can download a file with Ruby's stdlib? |
||
spec.add_runtime_dependency 'mercenary', '0.4.0' | ||
spec.add_runtime_dependency 'nokogiri', '~> 1.11' | ||
spec.add_runtime_dependency 'pango', '~> 3.4' | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch! I tend not to use this anymore.