Libgdx Missing LabelStyle font for ImageTextButton - json

I've been creating Button(s) just using the Button class, but figured I'd try the ImageTextButton. However, even with just the Button class, I'm not quite following the docs on how a .pack (atlas) file with a .json file should be working together.
Using the Button class, I can 'name' my button whatever I like in code, and have it named in the json accordingly (see examples below), but for 'Image's, I have to 'name' everything the same, from the construction in code, through the pack and json files. Example of what works:
code:
// note the 'Constants' just point to the json and atlas files, respectively.
skinShops = new Skin(Gdx.files.internal(Constants.SKIN_SHOPS), new
TextureAtlas(Constants.TEXTURE_ATLAS_SHOPS));
// for this next line, note the json definition for Button$ButtonStyle:
Button buttonBuy = new Button(skinShops, "Button-Buy");
// for Images, it seems I cannot have a 'unique' name first, then the drawable name, which I thought refers to the json
Image imgItemsBackground = new Image(skinShops, "shop-items-background");
If you look at the 'scene2d.ui.Image:' definitions, everything is named the same. While its working this way, I'm not clear why.
This could be 2 questions I guess, the previous concern about nomenclature of naming between all these elements, but my current issue I cannot get past is trying to construct an ImageTextButton. In code, I'm building them dynamically depending on where the player is: different shops have different items to sell, and those are read into the items[] array.
ImageTextButton buttonPurchase = new ImageTextButton(items[j], skinShops, "shop_item-button-background");
Stack trace:
Exception in thread "LWJGL Application" java.lang.IllegalArgumentException: Missing LabelStyle font.
at com.badlogic.gdx.scenes.scene2d.ui.Label.setStyle(Label.java:78)
at com.badlogic.gdx.scenes.scene2d.ui.Label.<init>(Label.java:72)
at com.badlogic.gdx.scenes.scene2d.ui.ImageTextButton.<init>(ImageTextButton.java:57)
at com.badlogic.gdx.scenes.scene2d.ui.ImageTextButton.<init>(ImageTextButton.java:44)
at com.uv.screen.InteriorScreen.buildItemButtons(InteriorScreen.java:134)
Where should I be creating / setting the font for these buttons?
json file:
{
com.badlogic.gdx.scenes.scene2d.ui.Button$ButtonStyle: {
Button-Exit: { down: Button_Exit_112x60, up: Button_Exit_112x60 },
Button-Buy: { down: Button_Buy_112x60, up: Button_Buy_112x60 },
Button-Sell: { down: Button_Sell_112x60, up: Button_Sell_112x60 }
},
com.badlogic.gdx.scenes.scene2d.ui.ImageTextButton$ImageTextButtonStyle: {
shop_item-button-background: { down: shop_item-button-background, up: shop_item-button-background }
},
com..badlogic.gdx.scenes.scene2d.ui.Image: {
background: { drawable: background },
shop-items-background: { drawable: shop-items-background },
shop-menu-background: { drawable: shop-menu-background },
shop-talk-text-background: { drawable: shop-talk-text-background },
weapon-shop-portrait_world1: { drawable: weapon-shop-portrait_world1 },
armor-shop-portrait_world1: { drawable: armor-shop-portrait_world1 },
item-shop-portrait_world1: { drawable: item-shop-portrait_world1 },
inn-shop-portrait_world1: { drawable: inn-shop-portrait_world1 }
}
atlas file:
shops-pack.png
format: RGBA8888
filter: Nearest,Nearest
repeat: none
background
rotate: false
xy: 0, 504
size: 800, 480
orig: 800, 480
offset: 0, 0
index: -1
shop-items-background
rotate: false
xy: 0, 248
size: 608, 256
orig: 608, 256
offset: 0, 0
index: -1
shop_item-button-background
rotate: false
xy: 0, 60
size: 256, 60
orig: 256, 60
offset: 0, 0
index: -1
...

There's no reason your Images in your json have to have the same names as the drawables in them. You don't even need to put Images in your skin. Look at the documentation of ImageTextButtonStyle...its parameters are Drawables, not Images. And so that's why it seems like you need to use the exact texture region names.
Skin automatically creates a TextureRegionDrawable or NinePatchDrawable out of a texture region with that name if you haven't created one in the Skin. But you can create all kinds of Drawables (such as TiledDrawable or TintedDrawable, or a TextureRegionDrawable with custom padding) and specify those as your button's image if you want to.
Also note in the documentation that ImageTextButtonStyle inherits a member named font from TextButtonStyle, which is not marked as optional in the documentation. So you're getting an exception for using an ImageTextButtonStyle that did not specify a font.
There are a couple ways you can put a font into your skin. If you have generated a bitmap font with a tool such as BMFont or Heiro, you can pack it into your texture atlas. Simply put the .fnt file and its image into the same directory with your other images that you are packing. And put another copy of the .fnt file into your assets directory, next to your atlas file. Then specify the font in your skin json by using its file name:
com.badlogic.gdx.graphics.g2d.BitmapFont: { myfont: { file: myfont.fnt } },
If you are using FreeTypeFontGenerator, this is more complicated. Let me know if that's what you're doing.

Related

Sheet.updateChart resets series color

I have the following chart:
And a script attached to the button:
function updateChart() {
const sheet = SpreadsheetApp.getActiveSheet()
const chart = sheet.getCharts()[0];
SpreadsheetApp.getUi().alert(String(chart.getOptions().get('title')));
SpreadsheetApp.getUi().alert(String(chart.getOptions().get('series.0.color')));
sheet.updateChart(chart.modify().build());
}
The first time I'm pressing this button it does nothing (as expected). The second time it resets line color to blue.
series.0.color is always null, although title is there, so I'm not even sure where to get that color to preserve it in between .modify() and .build() calls.
How do I prevent updateChart from resetting the color?
I've tried to inspect options in the published chart as suggested in comments (thanks #TheMaster), unfortunately it still doesn't help with the color issue.
The options are:
{
"hAxis": {
"title": "x"
},
"vAxes": {
"0": {
"title": "10x"
}
},
"series": {
"0": {
"color": "#008000"
}
},
"useFirstColumnAsDomain": true,
"width": 600,
"title": "10x vs \"x\"",
"height": 371
}
And I'm using the following code to get them:
function printOption(opts, name) {
console.log(`${name}: ${opts.get(name)}`)
}
function inspectChart(chart) {
const options = chart.getOptions();
printOption(options, 'title');
printOption(options, 'hAxis.title');
printOption(options, 'vAxes.0.title');
printOption(options, 'series.0.color');
}
Output is:
title: 10x vs "x"
hAxis.title: x
vAxes.0.title: 10x
series.0.color: null
As you can see all properties (including nested within array) are there except color
Another interesting point is that once you try to update the color:
sheet.updateChart(sheet.getCharts()[0].modify().setOption('series', {0: {color: 'green'}}).build());
It applies, but from now you're unable to read that property at all:
sheet.getCharts()[0].getOptions().get('series.0.color')
The line above fails with Unexpected error while getting the method or property get on object Charts.ChartOptions.
Also it looks like no matter what color I choose it is always #008000 in the published chart, which makes me think I should look for the color somewhere else, but I don't know where

Setting ticks of Chart.js in html.erb file

I'm using chartkick with chart.js in Ruby on Rails. I saw the documentation and some issues, but I can't find anything to solve my problem.
I'm setting my chart in html.erb file, like this:
<%=
line_chart $hash_chart,
options: {
max: $value.max+5,
min: $value.min-5,
allowDecimals: false,
colors: color_line,
xtitle: "Title of x axis",
ytitle: "Title of y axis",
discrete: true,
points: false,
width: "500px",
height: "500px",
scales: {
yAxes: [{
distribution: 'linear'
}],
xAxes: [{
distribution: 'linear',
type: 'category', (part of a configuration attempt)
categories: $time, (part of a configuration attempt)
ticks: {
stepSize: 10
}
}]
}
}
%>
The settings until height param works, but scales settings doesn't. The answer of this issue is exactly what I make (according documentation of Chart.js), but didn't work: Force display of ticks on xAxes using chartkick gem and chart.js. I tried to put this setting inside library brace too.
Basically, I want to set the ticks in x Axis and show just some labels of my array of datas. Is it possible to format this (using this type of file)?
You are using the wrong old v2 syntax of chart.js, the scales in v3 for example have to be configured like this
scales: {
x:{
ticks: {}
},
y: {
// Y config
}
}
EDIT:
Since you are on V2 your syntax of declaring axis is correct, make sure you dont run the latest version of chartKick since it uses v3.
distribution does not do anything unless your scale type is time. The stepSize only works for linear and time scales so you will need to change type: 'category' to type: 'linear' or if you are using time data to type: 'time' if you are using time data the stepsize has to be configured in the time sub part so you will need to change ticks to time

Vega-Lite: "1 in X" custom legend labels

I'm working on a choropleth map that shows the share of the population that has confirmed positive case of Covid-19 in each political jurisdiction. Similar to this example in the per capita Mapbox graphic on this page of the The New York Times.
I figured out just about every detail expect how to customize the legend. Currently, the labels display the shareOfPop as a number. Though, I want to prefix each label with "1 in ${shareOfPop}", and to add a suffix to the final label "1 in ${shareOfPop} or more".
enter image description here.
I've created this map in an Observable Notebook.
Things I've tried so far...
Making us of the custom legend encodings
To specify label text:
vl.color()
.fieldQ('shareOfPop')
.scale(
{
scheme: "yelloworangered",
domain: [250, 10],
clamp: true,
}
)
.legend({
title: "Share of Pop.",
encode: {
labels: {text: "1 in ${datum.value}"}
}
})
Register a custom formatter
Which I doubt I've accomplished correctly.
Here's what my configuration looks like (which is based on the config in the Introduction to Vega-Lite notebook).
vl = {
const [vega, vegalite, api, tooltip] = await Promise.all([
'vega#5.13.0',
'vega-lite#4.14.1',
'vega-lite-api#0.11.0',
'vega-tooltip#0.22.1'
].map(module => require(module)));
const options = {
config: {
// allow custom format types
customFormatTypes: true,
config: {
view: {continuousWidth: 400, continuousHeight: 300},
mark: {tooltip: null}
}
},
init: view => {
// initialize tooltip handler
view.tooltip(new tooltip.Handler().call);
// enable horizontal scrolling for large plots
if (view.container()) view.container().style['overflow-x'] = 'auto';
// register a custom expression function...am I doing this right???
vega.expressionFunction('1inX', function(datum) {
return `1 in ${datum}`
})
},
view: {
// view constructor options
loader: vega.loader({baseURL: 'https://cdn.jsdelivr.net/npm/vega-datasets#1/'}),
renderer: 'canvas'
}
};
return api.register(vega, vegalite, options);
}
Then I specify this custom formatType when defining the mark:
vl.color()
.fieldQ('shareOfPop')
.scale(
{
scheme: "yelloworangered",
domain: [250, 10],
clamp: true,
}
)
.legend({
title: "Share of Pop.",
formatType: "1inX",
})
)
Neither of these approaches produced any noticeable change.
Gonna answer my own question here.
Turns out Legend has a general labelExpr property that allows you to specify a Vega expression for customizing the label.
In my case, I wanted to always prepend the string "1 in ", and also append "+" when over may domain limit. Here's how I did it using the join() and if() functions.
...
vl.color()
.legend(
{
labelExpr: "join(['1 in ', datum.value, if(datum.value >= 250, '+', '')], '')"
}
)
This property isn't documented for Legend, though it is for for Axis).

Stack extruded polygons in 3D with the ArcGIS API for JavaScript

I have polygon geometries and visualize them in 3D using a ExtrudeSymbol3DLayer, as described in the SDK documentation and the sample:
var symbol = {
type: "polygon-3d", // autocasts as new PolygonSymbol3D()
symbolLayers: [{
type: "extrude", // autocasts as new ExtrudeSymbol3DLayer()
size: 5, // 5 meters in height
material: { color: "red" }
}]
};
Is there any way to stack these 3D extrusions on top of each other? For example, if I have a geometry for New York City, I want to extrude from the bottom to about 5m in one color, and 5m to 10m in one color, etc etc. Kind of like making a stacked bar chart, but in a more geographic way. Any input would be appreciated!
This is possible by extruding the geometries and placing them at a certain height using the elevationInfo property on the layer. The below example is assuming you have a layer (e.g. FeatureLayer or GeoJSONLayer) with polygon geometries.
For the extrusion, tell the layer to render the polygons with a ExtrudeSymbol3DLayer. In the below code snippet, all polygons will have a height of 5 meters.
layer.renderer = {
type: "simple",
symbol: {
type: "polygon-3d",
symbolLayers: [
{
type: "extrude",
size: 5, // height in meters
material: {
color: "red"
}
}
]
}
}
After that you can make your extruded polygons fly by placing them at a certain elevation relative-to-ground. The below example will renderer all polygons 10 meters above ground.
layer.elevationInfo = {
mode: "relative-to-ground",
offset: 10,
unit: "meters"
}
The polygons will not yet appear stacked as they all have the same color, height and elevation from the ground. We basically want to have different values in the above code snippets for each of the polygons.
The following example code achieves this by adding
an Arcade expression for the elevationInfo
a VisualVariable for the extruded height of the polygon
a UniqueValueRenderer to use a different color for each polygon
They all depend on the attributes of the polygon feature and can therefore be tweaked by changing the values of the attributes.
// Make elevation offset depend on the attribute "elevation"
layer.elevationInfo = {
mode: "relative-to-ground",
featureExpressionInfo: {
expression: "$feature.elevation"
},
unit: "meters"
};
layer.renderer = {
type: "unique-value",
visualVariables: [
// Make the extrusion height depend on the attribute "height"
{
type: "size",
valueExpression: "$feature.height",
valueUnit: "meters"
}
],
// Make the color depend on the attribute "usage"
field: "usage",
uniqueValueInfos: [
{
value: "office",
symbol: {
type: "polygon-3d",
symbolLayers: [
{
type: "extrude",
material: {
color: "#D06152"
}
}
]
}
},
... // Add unique value info for each usage
]
};
Here is a running example showing a few extruded polygons in Central Park, NY.
https://codepen.io/arnofiva/pen/4071d4e79a3cb921f42d6a9e83f5b418?editors=1010

How does CreateJs encrypt a path

I have following code which is responsible to generate a text, But i don't understand how does CreateJs is encrypting this text
this.shape_12.graphics.f("#00ADEA").s().p("Ag1Q...");
where .p("") is responsible for the rendering of text "Nursing",
I am stucked here because i want to change this text to the "MyArticle". any help how can i do this.
(lib.text_1_5 = function (mode, startPosition, loop) {
this.initialize(mode, startPosition, loop, {});
// timeline functions:
this.frame_0 = function () {
this.link = "Nursing";
this.on("click", function (event) {
canvasStageRef.onItemClick();
});
}
// actions tween:
this.timeline.addTween(cjs.Tween.get(this).call(this.frame_0));
// Layer 1//fontcolor
this.shape_10 = new cjs.Shape();
this.shape_10.graphics.f("#FF0000").s().p("AgsFJQgLAAgIgDQgIgDgFgGQgGgGgDgKQgCgJAAgMQAAgVAIgMQAIgNAPgCIAAAbQgEACgDAFQgEAEAAAKQAAALAGAGQAFAGALAAIALAAIAAgBQgFgEgEgHQgDgGAAgKQAAgLAFgLQAHgKAKgGQALgHAOAAQAPAAAMAGQAKAFAHAKQAGAKAAANQAAAKgEAHQgDAHgGAFIAAAAIAKAAIAAAagAgREHQgHAGAAALQAAAIADAGQAEAFAGADQAGACAGAAQAIAAAGgDQAGgCAFgGQADgFAAgIQAAgLgIgGQgGgGgOAAQgLAAgHAGgAg0DaIAAgbIA9AAQAIAAAFgFQAFgEABgJQgBgJgGgGQgHgGgLAAIg3AAIAAgbIBkAAIAAAbIgOAAIAAAAQAJAFADAIQAFAHAAALQAAAKgFAIQgFAIgJAFQgIAEgMAAgABABrIAAgbIAZAAIAAAbgAg0BrIAAgbIBkAAIAAAbgAgoA+QgIgFgDgKQgEgJgBgNQAAgXALgKQAJgMAQgBIAAAXQgIABgEAGQgFAGABAJQAAAJADAFQADAFAGAAQAEAAADgEIADgKIADgNIAFgQQADgIAEgFQAGgFALAAQALAAAIAFQAHAGADAHQAEAKAAALQAAAVgKALQgIALgQABIAAgYQAIgBAEgFQADgFAAgJQAAgIgDgFQgDgEgGgBQgEABgCADIgEALIgCAOQgCAIgDAJQgDAIgFAFQgFAGgNAAQgKAAgHgGgAAZgbIAAAAQABgOgHgIQgHgJgPAAIgxAAIAAgbIBkAAIAAAaIgRAAIAAABQAKAEAEAGQAFAGgBAJIAAAEIgBACgAg0hmIAAgbIALAAIAAAAQgGgFgEgHQgEgHgBgLQABgRAKgJQAJgJASAAIBCAAIAAAbIg+AAQgJAAgEAEQgGAEAAAJQABAJAGAGQAHAFAKAAIA5AAIAAAcgAg0jVIAAgcIBNgxIAIgFIAIgDIADgCIAAAAIgEAAIgKAAIgLAAIhHAAIAAgcICNAAIAAAdIhQAwIgJAEIgGAEIgDACIAAAAIAEAAIAHAAIALgBIBMAAIAAAdg");
this.shape_10.setTransform(-1.5, -9);
this.timeline.addTween(cjs.Tween.get({}).to({ state: [{ t: this.myText }] }).wait(1));
above code is responsible to render text Nursing(in .p("ahskjhsja");)... plz suggest which thing i will replace to make it text that is not render with path... it can change manually..
if this is possible with Text than how i can acheive plz help.. :(
This is not an encryption but path specification similar to path in SVG. You can define complex path by hand but when you need to draw a text data you should really try Text first.
Yes i got a solution with above answer .. and also giving exact right answer,, Thanks to #oleg and Lanny
this.shape= new cjs.Text("Cardic surgery", "bold 17px Arial", "#9aac5a");
this.shape.setTransform(25, -118, 1.0, 1.0, 90, 0, 0, -30, 1.0);
this.timeline.addTween(cjs.Tween.get({}).to({ state: [{ t: this.shape }] }).wait(1));