scenicframework / scenic Goto Github PK
View Code? Open in Web Editor NEWCore Scenic library
License: Apache License 2.0
Core Scenic library
License: Apache License 2.0
Right now the mailing list is pointing to Phoenix framework mailing list on the Feature Requests section
I’m trying to load a custom font like this:
Scenic.Cache.Hash.compute(File.read!(@font_path), :sha) |> IO.inspect()
Scenic.Cache.File.load(@font_path, @font_hash) |> IO.inspect()
Scenic.Cache.File.read(@font_path, @font_hash) |> IO.inspect()
graph =
Graph.build(font: @font_hash, font_size: 24)
This is the output when using the font:
"cu1h9EqFbnBMyCyDDqtWtMh2lOw"
{:ok, "cu1h9EqFbnBMyCyDDqtWtMh2lOw"}
{:ok,
<<0, 1, 0, 0, 0, 20, 1, 0, 0, 4, 0, 64, 71, 80, 79, 83, 39, 13, 154, 194, 0, 4,
82, 12, 0, 0, 117, 60, 71, 83, 85, 66, 177, 57, 193, 22, 0, 4, 199, 72, 0, 0,
0, 146, 76, 84, 83, 72, ...>>}
Unknown message: 0x38
WARNING Excess message bytes! 313343
So it looks like loading/reading the file works fine, but when I use it I get the error message.
It’s a ttf font.
(I've first posted this on the forum, but as this probably is a bug (or lacking documentation) I'm putting it here as well)
The structure and format of the commented out lines of metadata at the top of files is currently inconsistent, and in some cases incomplete, or missing.
As a first step in establishing a canonical structure and format for the metadata at the top of files - the various date formats used for the creation date have been re-written in an ISO-8601 compliant format.
This will allow an automated pass over the files in the repository to identify files where the metadata is currently inconsistent, incomplete, or missing.
An Issue (to be raised after this one) will propose for adoption if found to be satisfactory - a simple structure and format for the metadata at the top of files.
Note: The choice of the ISO-8601 date format is to eliminate the several ambiguities that arise from the inevitable mixed use of US mm/dd/yy formats and other formats used around the globe.
First, congratulations on an exceptional achievement. Nicely done.
These days I'm on a mission to create Elixir code with smaller chunks of things, where a chunk could be a module, function, or even expression. Looking through this code, it seems like you're already there.
So I have a small suggestion for the example code generated by new.scenic.example.
Take the primitives code as an example. Right now, it looks like this:
defmodule Xx.Scene.Primitives do
@moduledoc """
Sample scene.
"""
use Scenic.Scene
alias Scenic.Graph
import Scenic.Primitives
alias Xx.Component.Nav
alias Xx.Component.Notes
@bird_path :code.priv_dir(:xx)
|> Path.join("/static/images/cyanoramphus_zealandicus_1849.jpg")
@bird_hash Scenic.Cache.Hash.file!( @bird_path, :sha )
@bird_width 100
@bird_height 128
@body_offset 80
@line {{0, 0}, {60, 60}}
@notes """
\"Primitives\" shows the various primitives available in Scenic.
It also shows a sampling of the styles you can apply to them.
"""
@graph Graph.build(font: :roboto, font_size: 24)
|> group(
fn g ->
g
|> text("Various primitives and styles", translate: {15, 20})
# lines
|> group(
fn g ->
g
|> line(@line, stroke: {4, :red})
|> line(@line, stroke: {20, :green}, cap: :butt, t: {60, 0})
|> line(@line, stroke: {20, :yellow}, cap: :round, t: {120, 0})
end,
t: {290, 50}
)
# row
|> group(
fn g ->
g
|> triangle({{0, 60}, {50, 0}, {50, 60}}, fill: :khaki, stroke: {4, :green})
|> circle(30, fill: :green, stroke: {6, :yellow}, t: {110, 30})
|> ellipse({30, 40}, rotate: 0.5, fill: :green, stroke: {4, :gray}, t: {200, 30})
end,
t: {15, 50}
)
# row
|> group(
fn g ->
g
|> rect({50, 60}, fill: :khaki, stroke: {4, :green})
|> rrect({50, 60, 6}, fill: :green, stroke: {6, :yellow}, t: {85, 0})
|> quad({{0, 100}, {160, 0}, {300, 110}, {200, 260}},
id: :quad,
fill: {:linear, {0, 0, 400, 400, :yellow, :purple}},
stroke: {10, :khaki},
translate: {160, 0},
scale: 0.3,
pin: {0, 0}
)
|> sector({100, -0.3, -0.8},
stroke: {3, :grey},
fill: {:radial, {0, 0, 20, 160, {:yellow, 128}, {:purple, 128}}},
translate: {270, 70}
)
|> arc({100, -0.1, -0.8}, stroke: {6, :orange}, translate: {320, 70})
end,
t: {15, 130}
)
# bird
|> rect({@bird_width, @bird_height}, fill: {:image, @bird_hash}, t: {15, 230})
# text
|> group(
fn g ->
g
|> text("Hello", translate: {0, 40})
|> text("World", translate: {90, 40}, fill: :yellow)
|> text("Blur", translate: {0, 80}, font_blur: 2)
|> text("Shadow", translate: {82, 82}, font_blur: 2, fill: :light_grey)
|> text("Shadow", translate: {80, 80})
end,
font_size: 40,
t: {130, 240}
)
# twisty path
|> path(
[
:begin,
{:move_to, 0, 0},
{:bezier_to, 0, 20, 0, 50, 40, 50},
{:bezier_to, 60, 50, 60, 20, 80, 20},
{:bezier_to, 100, 20, 110, 0, 120, 0},
{:bezier_to, 140, 0, 160, 30, 160, 50}
],
stroke: {2, :red},
translate: {355, 230},
rotate: 0.5
)
end,
translate: {15, @body_offset}
)
# Nav and Notes are added last so that they draw on top
|> Nav.add_to_graph(__MODULE__)
|> Notes.add_to_graph(@notes)
def init(_, _opts) do
# load the parrot texture into the cache
Scenic.Cache.File.load(@bird_path, @bird_hash)
push_graph(@graph)
{:ok, @graph}
end
end
The @graph
attribute is scary long, and I constantly messed up brackets when messing with it. So how about continuing the compile-time attribute goodness by splitting it further?
defmodule Me1.Scene.Primitives do
@moduledoc """
Sample scene.
"""
use Scenic.Scene
alias Scenic.Graph
import Scenic.Primitives
alias Me1.Component.Nav
alias Me1.Component.Notes
@bird_path :code.priv_dir(:me1)
|> Path.join("/static/images/cyanoramphus_zealandicus_1849.jpg")
@bird_hash Scenic.Cache.Hash.file!( @bird_path, :sha )
@bird_width 100
@bird_height 128
@body_offset 80
@line {{0, 0}, {60, 60}}
@notes """
\"Primitives\" shows the various primitives available in Scenic.
It also shows a sampling of the styles you can apply to them.
"""
@lines fn g ->
g
|> line(@line, stroke: {4, :red})
|> line(@line, stroke: {20, :green}, cap: :butt, t: {60, 0})
|> line(@line, stroke: {20, :yellow}, cap: :round, t: {120, 0})
end
@triangle_circle_ellipse fn g ->
g
|> triangle({{0, 60}, {50, 0}, {50, 60}}, fill: :khaki, stroke: {4, :green})
|> circle(30, fill: :green, stroke: {6, :yellow}, t: {110, 30})
|> ellipse({30, 40}, rotate: 0.5, fill: :green, stroke: {4, :gray}, t: {200, 30})
end
# or possibly using & function literals??
@filled_stuff & &1
|> rect({50, 60}, fill: :khaki, stroke: {4, :green})
|> rrect({50, 60, 6}, fill: :green, stroke: {6, :yellow}, t: {85, 0})
|> quad({{0, 100}, {160, 0}, {300, 110}, {200, 260}},
id: :quad,
fill: {:linear, {0, 0, 400, 400, :yellow, :purple}},
stroke: {10, :khaki},
translate: {160, 0},
scale: 0.3,
pin: {0, 0}
)
|> sector({100, -0.3, -0.8},
stroke: {3, :grey},
fill: {:radial, {0, 0, 20, 160, {:yellow, 128}, {:purple, 128}}},
translate: {270, 70}
)
|> arc({100, -0.1, -0.8}, stroke: {6, :orange}, translate: {320, 70})
@text & &1
|> text("Hello", translate: {0, 40})
|> text("World", translate: {90, 40}, fill: :yellow)
|> text("Blur", translate: {0, 80}, font_blur: 2)
|> text("Shadow", translate: {82, 82}, font_blur: 2, fill: :light_grey)
|> text("Shadow", translate: {80, 80})
@path &path(&1,
[
:begin,
{:move_to, 0, 0},
{:bezier_to, 0, 20, 0, 50, 40, 50},
{:bezier_to, 60, 50, 60, 20, 80, 20},
{:bezier_to, 100, 20, 110, 0, 120, 0},
{:bezier_to, 140, 0, 160, 30, 160, 50}
],
stroke: {2, :red},
translate: {355, 230},
rotate: 0.5)
@graph Graph.build(font: :roboto, font_size: 24)
|> group(
fn g ->
g
|> text("Various primitives and styles", translate: {15, 20})
|> group(@lines, t: {290, 50})
|> group(@triangle_circle_ellipse, t: {15, 50})
|> group(@filled_stuff, t: {15, 130})
|> rect({@bird_width, @bird_height}, fill: {:image, @bird_hash}, t: {15, 230})
|> group(@text, font_size: 40, t: {130, 240})
|> group(@path)
end,
translate: {15, @body_offset}
)
# Nav and Notes are added last so that they draw on top
|> Nav.add_to_graph(__MODULE__)
|> Notes.add_to_graph(@notes)
def init(_, _opts) do
# load the parrot texture into the cache
Scenic.Cache.File.load(@bird_path, @bird_hash)
push_graph(@graph)
{:ok, @graph}
end
end
You can see I switched styles from using fn
to using &
half way through just to see what each looked like.
Waddya think?
Dave
(ps: I think I get major credit for not showing you my solution using macros... :)
~/elixir -v
Erlang/OTP 21 [erts-10.2.4] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [hipe]
Elixir 1.8.1 (compiled with Erlang/OTP 21)
~/
Scenic:
OS:
OSX
https://github.com/QuantumProductions/scenic_font_test
I tried to install a Courier New font following https://github.com/boydm/scenic/blob/master/guides/custom_fonts.md
In GameOver.ex there is
@font_folder :code.priv_dir(:play) |> Path.join("/static/fonts")
@custom_font_hash "UYe2ryfLUpczug9LKyrTxPYGSYTimnPHzpSMbC6UF0M"
@custom_metrics_path :code.priv_dir(:scenic_example)
|> Path.join("/static/fonts/Courier New.ttf.metrics")
@custom_metrics_hash Scenic.Cache.Support.Hash.file!(@custom_metrics_path, :sha)
==> play
make: Nothing to be done for `all'.
Compiling 4 files (.ex)
== Compilation error in file lib/scenes/game_over.ex ==
** (FunctionClauseError) no function clause matching in IO.chardata_to_string/1
The following arguments were given to IO.chardata_to_string/1:
# 1
{:error, :bad_name}
Attempted function clauses (showing 2 out of 2):
def chardata_to_string(string) when is_binary(string)
def chardata_to_string(list) when is_list(list)
(elixir) lib/io.ex:461: IO.chardata_to_string/1
(elixir) lib/path.ex:512: Path.join/2
lib/scenes/game_over.ex:9: (module)
(stdlib) erl_eval.erl:680: :erl_eval.do_apply/6
could not compile dependency :play, "mix compile" failed. You can recompile this dependency with "mix deps.compile play", update it with "mix deps.update play" or clean it with "mix deps.clean play"
Name of font does not seem to be accepted. I downloaded from https://www.wfonts.com/font/courier-new
Elixir:
# elixir -v
Erlang/OTP 21 [erts-10.0.5] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:1] [hipe]
Elixir 1.7.2 (compiled with Erlang/OTP 19)
Erlang:
# erl -v
Erlang/OTP 21 [erts-10.0.5] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:1] [hipe]
Eshell V10.0.5 (abort with ^G)
Scenic:
# mix deps | grep scenic
* scenic_sensor 0.7.0 (Hex package) (mix)
locked at 0.7.0 (scenic_sensor) a12aed75
* scenic 0.8.0 (Hex package) (mix)
locked at 0.8.0 (scenic) 44bffa47
* scenic_driver_glfw 0.8.1 (Hex package) (mix)
locked at 0.8.1 (scenic_driver_glfw) 4fceea7b
* scenic_clock 0.8.0 (Hex package) (mix)
locked at 0.8.0 (scenic_clock) fc144430
OS:
# uname -a
Linux 4.15.0-33-generic #36~16.04.1-Ubuntu SMP Wed Aug 15 17:21:05 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux
Graph.build()
in lib/scenes/splash.ex:22 to Graph.build(clear_color: :white)
and/or change theme: :dark
to theme: :light
in lib/scenes/transforms.ex:21.The background fill in the parrot splash screen is changed from black to white, and/or the theme colors in the transforms screen are changed to brighter tones.
The colors are unchanged, and the screens are visually the same.
n/a
theme: %{background: :white}
with no success either. Other color-related options such as :fill
are working as expected.The root scene should inherit both a style map and a transforms that have been set on the ViewPort via it's configuration record.
In this way, you can set something like a :scale transform on the ViewPort and all scene's it shows would be zoomed in or repositioned or whatever.
Same for supplying ViewPort specific defaults for the styles.
Elixir:
# elixir -v
Erlang/OTP 21 [erts-10.0.8] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [hipe]
Elixir 1.7.3 (compiled with Erlang/OTP 21)
Erlang:
# erl -v
Erlang/OTP 21 [erts-10.0.8] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [hipe]
Scenic:
# mix deps | grep scenic
* scenic_sensor 0.7.0 (Hex package) (mix)
locked at 0.7.0 (scenic_sensor) a12aed75
* scenic 0.8.0 (Hex package) (mix)
locked at 0.8.0 (scenic) 44bffa47
* scenic_driver_glfw 0.8.0 (Hex package) (mix)
locked at 0.8.0 (scenic_driver_glfw) 710e0256
* scenic_clock 0.8.0 (Hex package) (mix)
locked at 0.8.0 (scenic_clock) fc144430
OS:
# uname -a
Arch Linux 4.18.9-arch1-1-ARCH #1 SMP PREEMPT Wed Sep 19 21:19:17 UTC 2018 x86_64 GNU/Linux
*with wayland*
The example app window shows up with correct positioning.
The rendered output only takes up a quarter of the whole window. The areas for buttons and drop downs are positioned correctly which means to have to click into the empty black part of the window to hit something.
Sadly there is not a lot to see here, just a single message from GLFW.
mix scenic.run
GLFW error 65544: Wayland: Focusing a window requires user interaction
I think the examples for Scenic.Components.text_field/3
are not updated. I might be wrong.
graph
|> text_field( {"Sample Text", :text_id}, translate: {20,20} )
graph
|> text_field(
{"", :pass_id, [type: :password, hint: "Enter password"]},
translate: {20,20}
)
The updated examples should be as follow:
graph
|> text_field( "Sample Text", id: :text_id, translate: {20,20} )
graph
|> text_field( "", id: :pass_id, type: :password, hint: "Enter password",
translate: {20,20}
)
The examples code cause the app crash and restart continuously until we manually quit the process by Ctrl-C
, which may also be an issue. If it is a concern, would it be better if we can impose limit on the restart attempt caused by such error, so we can avoid the supervisor to crash and restart indefinitely?
To reproduce the issue,
git clone https://github.com/kw7oe/scenic_demo.git
cd scenic_demo
mix deps.get
mix scenic.run
Point me to the right direction if I am wrong, since I am fairly inexperience.
Thanks for the efforts in making this project. Really appreciate it.
Rendering glitch shows up from time to time with the example app (scenic_new repo), sensor scene, :temperature text component.
Elixir:
# elixir -v
Erlang/OTP 21 [erts-10.1.2] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:1] [hipe] [dtrace]
Elixir 1.7.4 (compiled with Erlang/OTP 21)
Erlang:
# erl -v
Erlang/OTP 21 [erts-10.1.2] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:1] [hipe] [dtrace]
Eshell V10.1.2 (abort with ^G)
Scenic:
# mix deps | grep scenic
* scenic_sensor 0.7.0 (Hex package) (mix)
locked at 0.7.0 (scenic_sensor) a12aed75
* scenic 0.9.0 (Hex package) (mix)
locked at 0.9.0 (scenic) 129594f9
* scenic_driver_glfw 0.9.0 (Hex package) (mix)
locked at 0.9.0 (scenic_driver_glfw) 4c7a8300
* scenic_clock 0.8.0 (Hex package) (mix)
locked at 0.8.0 (scenic_clock) fc144430
OS:
MacOS Mojave 10.14.1
mix scenic.new.example
It should show the temperature as usual. Here's what it looks like before the issue:
But then his happens (here when displaying 72.8°):
It looks like texts around it get mixed up.It lasts only a few milliseconds (captured from a video recording of the screen), then things go back to normal.
I can reproduce the issue most of the times.
n/a
I checked with IO.inspect the text given to the component (temperature), it's correct. Looks like the issue is from scenic, not the example project itself.
Elixir: 1.8.1-otp-21
Erlang: 21.2.2
Scenic: 0.10.0
OS: MacOS
Graph.build(font_size: 22, font: :roboto_mono, theme: :light)
|> text("System")
|> button("System")
Text would default to a dark color for the light theme and be visible.
Text is not a component, it is a primitive, which means it ignores the theme and renders white by default. The text ends up invisible.
The text inside the button is handled as expected and visible.
After some discussion with Emilio I believe this works as intended but I'd say it doesn't work the way you'd expect. I think following the theme is the work of the component, not the primitive. But the default way of putting arbitrary text on the screen is using the primitive. So we get no good default for the theming. Would it be reasonable for text to pick up the theme for default text color?
I think there is a potential for UI developer incredulity at why text just doesn't respect the theme setting. Do we want a component that simply wraps text and does the theming? What is that called? A Label? A ThemedText?
Elixir:
# elixir -v
Erlang/OTP 21 [erts-10.0.7] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:1] [hipe]
Elixir 1.7.3 (compiled with Erlang/OTP 21)
Erlang:
# erl -v
Erlang/OTP 21 [erts-10.0.7] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:1] [hipe]
Eshell V10.0.7 (abort with ^G)
Scenic:
# mix deps | grep scenic
* scenic_sensor 0.7.0 (Hex package) (mix)
locked at 0.7.0 (scenic_sensor) a12aed75
* scenic 0.9.0 (Hex package) (mix)
locked at 0.9.0 (scenic) 129594f9
* scenic_clock 0.8.0 (Hex package) (mix)
locked at 0.8.0 (scenic_clock) fc144430
OS:
Arch Linux
ViewPort.set_root/2
push_graph
in the init/1
callbackThe new scene/graph should be rendered
I only see a black screen (unless I add a delay to the push_graph
call of around 100ms)
I'm not sure if I'm misunderstanding something (although that is definitely possible). For testing I'm actually using the Splash Scene from scenic_new
so I don't think it is an issue with the scene transition (although I did look into it, which is why I was looking for the existence of release_graph
).
This is about clearing up all the refactoring opportunities that Credo complains about.
Next chunk of credo issues to resolve are modules missing a @moduledoc
tag.
This issue is about adding in ones--probably @moduledoc false
for now--to shutup credo and give people a place to start writing in more documentation.
Elixir:
# elixir -v
Elixir 1.7.3 (compiled with Erlang/OTP 19)
Erlang:
# erl -v
Erlang/OTP 21 [erts-10.0] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:1] [hipe]
Scenic:
# mix deps | grep scenic
* scenic_sensor 0.7.0 (Hex package) (mix)
locked at 0.7.0 (scenic_sensor) a12aed75
* scenic_math 0.7.1 (Hex package) (mix)
locked at 0.7.1 (scenic_math) 131ef7cf
* scenic 0.7.0 (Hex package) (mix)
locked at 0.7.0 (scenic) fa93041f
* scenic_driver_glfw 0.7.0 (Hex package) (mix)
locked at 0.7.0 (scenic_driver_glfw) e9051384
* scenic_clock 0.7.0 (Hex package) (mix)
locked at 0.7.0 (scenic_clock) 645bfd0f
OS:
Linux parrot 4.18.0-parrot8-amd64 #1 SMP Parrot 4.18.6-1parrot8 (2018-09-07) x86_64 GNU/Linux
(alternatively clone this repo and check the commits.
Create a new application using mix scenic.new example
.
Edit the application file to use Application
:
defmodule Example do
@moduledoc """
Starter application using the Scenic framework.
"""
use Application
def start(_type, _args) do
# import Supervisor.Spec, warn: false
# load the viewport configuration from config
main_viewport_config = Application.get_env(:example, :viewport)
# start the application with the viewport
# removed `supervisor/2` wrapper
children = [
Example.Sensor.Supervisor,
{Scenic, [viewports: [main_viewport_config]]},
]
Supervisor.start_link(children, strategy: :one_for_one)
end
end
Example.Sensor.Supervisor.start_link
:...
def start_link(_args) do
Supervisor.start_link(__MODULE__, :ok)
end
...
The application should have started normally.
The application didn't started because Scenic.child_spec/1
doesn't specify an :id
.
** (Mix) Could not start application example: Example.start(:normal, []) returned an error: bad child specification, got: :missing_id
This issue can be fixed by adding the :id
option to the list returned by Scenic.child_spec/1
:
...
def child_spec(opts) do
%{
id: __MODULE__, # adding this option
start: {__MODULE__, :start_link, [opts]},
type: :supervisor,
restart: :permanent,
shutdown: 500
}
end
...
Elixir: 1.7
Erlang: 21
Scenic:
scenic 0.9.0 (Hex package) (mix)
locked at 0.9.0 (scenic) 129594f9
scenic_driver_glfw 0.9.0 (Hex package) (mix)
locked at 0.9.0 (scenic_driver_glfw) 4c7a8300
OS: Ubuntu 16.04
text_field("", id: :text, width: 40, hint: "Type here...", t: {200, 160})
Width of the component to be 40
Defaults to 240
Struct From Inspection:
data: {Scenic.Component.Input.TextField, ""},
id: :key_input,
module: Scenic.Primitive.SceneRef,
parent_uid: 1,
styles: %{
fontsize: 15,
height: 20,
hint: "Paste Private Key or Pneumonic",
t: {100, 200},
w: 1000
},
transforms: %{translate: {100, 200}}
}
Any Width inputted doesn't change the width, I've used :w and :width as per the docs
I'm trying to test an updated version of scenic_new with a correspondingly updated version of scenic.
The problem is that the code generated by scenic_new includes
{:scenic, github: "pragdave/scenic", branch: "add-specs"},
{:scenic_driver_glfw, "~> 0.9"}
But :scenic_driver_glfw
also has a dependency on scenic, which it satisfies from hex. As a result, I get an error on deps.get
When I try to use :override to force just my version to be used, I get explosions inside glfw
20:46:42.323 [error] GenServer :glfw terminating
** (UndefinedFunctionError) function Scenic.Cache.request_notification/1 is undefined or private
(scenic) Scenic.Cache.request_notification(:cache_put)
(scenic_driver_glfw) lib/glfw.ex:82: Scenic.Driver.Glfw.init/3
(scenic) lib/scenic/view_port/driver.ex:153: Scenic.ViewPort.Driver.handle_cast/2
(stdlib) gen_server.erl:616: :gen_server.try_dispatch/4
(stdlib) gen_server.erl:686: :gen_server.handle_msg/6
(stdlib) proc_lib.erl:247: :proc_lib.init_p_do_apply/3
Last message: {:"$gen_cast", {:after_init, #PID<0.4413.0>, {700, 600}, %{module: Scenic.Driver.Glfw, name: :glfw, opts: [resizeable: false, title: "dave"]}}}
State: nil
Is there some magic I'm missing?
other functions with the same argument graph_or_primitive
also have a definition with a Primitive
struct, but it seems this is not implemented for group.
I'm not sure if group should not expect a primitive or if it's just not implemented?
Next to stating the issue, I'm also adding my problem here. I'm trying to use Graph.modify to update a complete group but I have no idea how to do it.
This is some simplified code:
Graph.build()
|> ....
|> group(
fn g -> builds_many(g), id: :sample
)
def builds_many(g) do
g
|> rrect(...)
end
And on an update I want to basically replace the group sample
by doing builds_many
again.
These are the things I tried:
Graph.modify
, but this has the problem that I get a primitive (a group) and rrect
can only take a Primitive of round_rect
not group.Primitive
with Graph.delete
, then building a new graph (It's not possible to just create a group from nothing), creating a new group and then try to add this graph to the main
graph, but Graph.add
expects a primitive so this doesn't workGraph.map
, but this action also passes a Primitive
I'm probably missing something here, but I'm still struggling with it, and that's the reason I stumbled on this issue.
I often find myself wanting to apply a gradient to a shape, rather than just a single color.
Maybe an API like this:
graph
|> rectangle( {100, 200}, fill: {:gradient, [0x6db1ec, 0x35a274], 90})
where fill
's options are {:gradient, list_of_colors, angle}
Currently each Graph that has text primitives must explicitly set both the font and font_size styles. The graph should have a sensible default if these styles are not supplied.
Suggestions:
font default should be :roboto
font_size default should be: 24
Looking to create a simple notepad app but didn't see a text area. Does this exist or is it possible somehow to get a large text input?
elixir -v
Erlang/OTP 21 [erts-10.3] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [hipe] [dtrace]
Elixir 1.8.1 (compiled with Erlang/OTP 21)
Scenic:
mix deps | grep scenic
* scenic_sensor 0.7.0 (Hex package) (mix)
locked at 0.7.0 (scenic_sensor) a12aed75
* scenic 0.10.2 (Hex package) (mix)
locked at 0.10.2 (scenic) f4f0a00e
* scenic_clock 0.10.0 (Hex package) (mix)
locked at 0.10.0 (scenic_clock) 5be4a87e
OS:
Mac OS 10.13.4 (17E199)
### Steps to reproduce
https://github.com/boydm/scenic_new
### Actual Behavior
mix deps.get
Resolving Hex dependencies...
Dependency resolution completed:
New:
elixir_make 0.6.0
font_metrics 0.3.1
msgpax 2.2.3
scenic 0.10.2
scenic_clock 0.10.0
scenic_driver_glfw 0.10.0
scenic_sensor 0.7.0
* Getting scenic (Hex package)
* Getting scenic_driver_glfw (Hex package)
* Getting scenic_sensor (Hex package)
* Getting scenic_clock (Hex package)
* Getting elixir_make (Hex package)
* Getting font_metrics (Hex package)
* Getting msgpax (Hex package)
mix scenic.run
==> msgpax
Compiling 8 files (.ex)
Generated msgpax app
==> font_metrics
Compiling 2 files (.ex)
Generated font_metrics app
==> scenic_sensor
Compiling 1 file (.ex)
Generated scenic_sensor app
==> elixir_make
Compiling 1 file (.ex)
Generated elixir_make app
==> scenic
mkdir -p /Users/xman/elixir-learning/my_app/_build/rpi3_dev/lib/scenic/ebin/../priv
cp -rf static /Users/xman/elixir-learning/my_app/_build/rpi3_dev/lib/scenic/ebin/../priv/static
mkdir -p /Users/xman/elixir-learning/my_app/_build/rpi3_dev/lib/scenic/ebin/../obj
cc -c -I/usr/local/Cellar/erlang/21.3/lib/erlang/usr/include -fPIC -O2 -Wall -Wextra -Wno-unused-parameter -std=c99 -o /Users/xman/elixir-learning/my_app/_build/rpi3_dev/lib/scenic/ebin/../obj/line.o c_src/line.c
cc /Users/xman/elixir-learning/my_app/_build/rpi3_dev/lib/scenic/ebin/../obj/line.o -L/usr/local/Cellar/erlang/21.3/lib/erlang/usr/lib -fPIC -shared -dynamiclib -undefined dynamic_lookup -o /Users/xman/elixir-learning/my_app/_build/rpi3_dev/lib/scenic/ebin/../priv/line.so
cc -c -I/usr/local/Cellar/erlang/21.3/lib/erlang/usr/include -fPIC -O2 -Wall -Wextra -Wno-unused-parameter -std=c99 -o /Users/xman/elixir-learning/my_app/_build/rpi3_dev/lib/scenic/ebin/../obj/matrix.o c_src/matrix.c
cc /Users/xman/elixir-learning/my_app/_build/rpi3_dev/lib/scenic/ebin/../obj/matrix.o -L/usr/local/Cellar/erlang/21.3/lib/erlang/usr/lib -fPIC -shared -dynamiclib -undefined dynamic_lookup -o /Users/xman/elixir-learning/my_app/_build/rpi3_dev/lib/scenic/ebin/../priv/matrix.so
cc -c -I/usr/local/Cellar/erlang/21.3/lib/erlang/usr/include -fPIC -O2 -Wall -Wextra -Wno-unused-parameter -std=c99 -o /Users/xman/elixir-learning/my_app/_build/rpi3_dev/lib/scenic/ebin/../obj/texture.o c_src/texture.c
cc /Users/xman/elixir-learning/my_app/_build/rpi3_dev/lib/scenic/ebin/../obj/texture.o -L/usr/local/Cellar/erlang/21.3/lib/erlang/usr/lib -fPIC -shared -dynamiclib -undefined dynamic_lookup -o /Users/xman/elixir-learning/my_app/_build/rpi3_dev/lib/scenic/ebin/../priv/texture.so
Compiling 91 files (.ex)
Generated scenic app
==> scenic_clock
Compiling 3 files (.ex)
Generated scenic_clock app
==> my_app
Compiling 11 files (.ex)
Generated my_app app
** (Mix) Could not start application my_app: MyApp.start(:normal, []) returned an error: shutdown: failed to start child: Scenic
** (EXIT) shutdown: failed to start child: Scenic.ViewPort.SupervisorTop
** (EXIT) shutdown: failed to start child: :main_viewport
** (EXIT) shutdown: failed to start child: Scenic.ViewPort.Driver.Supervisor
** (EXIT) an exception was raised:
** (ArgumentError) The module Scenic.Driver.Glfw was given as a child to a supervisor but it does not exist.
(elixir) lib/supervisor.ex:629: Supervisor.init_child/1
(elixir) lib/enum.ex:1327: Enum."-map/2-lists^map/1-0-"/2
(elixir) lib/supervisor.ex:615: Supervisor.init/2
(stdlib) supervisor.erl:295: :supervisor.init/1
(stdlib) gen_server.erl:374: :gen_server.init_it/2
(stdlib) gen_server.erl:342: :gen_server.init_it/6
(stdlib) proc_lib.erl:249: :proc_lib.init_p_do_apply/3
Is there a method to produce an image (in my case QR Code which is rendered to a png) and then have it displayed via the normal fill method (fill: {:img}) currently i can get it to render once but it takes ~4secs for the png to render correctly so nothing is displayed on the second attempt
Alternatively, I have the output of the QR Code as binary, is there a method to render a group of rectangles given a list? i.e i have a list:
[1,1,1,0]
it should render three white squares and one black square next to it. Digging around in the core library yesterday i played with grouping etc, but i think i need a little more info for it
What if instead of calling send_event/1
, we returned a list of events, sort of how we return the new Graph to push?
I'm not sure if this is a proper feature request or whatever, but now that graph-pushing has been moved to handler return value it kind of stuck out to me that event sending isn't, if that makes sense. Please go ahead and close this if it's not interesting to discuss (or the wrong place to have that discussion!)
This is a user experience thing I noticed while playing with the example (solid instructions for getting up and running, by the way, good job).
The slider elements (dragging a marker on a line) stop tracking your mouse's horizontal position if you move outside of the bounds of the widget. It stops dragging but will resume if you re-enter the bounds.
This felt awkward so I verified with some system components and at least on Mac (volume settings for example) they will, as I suspected keep tracking even if you go somewhere else vertically. As long as you keep the button pressed you have control of the slider.
I think this will mostly make the widget feel better. But it should also improve accessibility since it will no longer require the user to be quite as precise. So I think this would be a better default behavior.
Once you press down on the element to grab a hold of it you should keep that hold until you release, even if you go out-of-bonds on the vertical axis. I have not checked if this would straight forward or more complex in the code yet. This way just something I noticed while trying the feel of the widgets.
Let me know if anything seems unclear and I'll try to clarify :)
It would be useful for the scene to be able to obtain the metrics (width, height, etc) of a string of text before it gets rendered. For example, the Button component could use this to automatically size the button to fit the string. Any future (optional) layout engine would also need it.
This should NOT parse fonts at runtime. Interpreting fonts should remain the purview of the Drivers. In the future I want to support other font types than *.ttf and the core Scenic library should not have a dependency on that format.
Instead, I want to back the font metric information into separate format offline that can be easily loaded and inspected by a scene. No C code should be invoked at that time. This work is under way, but has been lower priority as most (all) scenes so far simply don't need it.
so, i want to lock my scenic app to kiosk mode
I believe the module name carat is misspelled. Fixing this would be a breaking change, so perhaps this must be treated urgently.
https://www.gingersoftware.com/english-online/spelling-book/confusing-words/carat-caret-karat-carrot
The repro is vague, but goes something like this:
Have not figured this out yet. I suspect there is some sort of blocking read or write between the driver (in erlang space) and the port that does the rendering. Don't know yet why that should be triggered by crashes in scenes, which is pretty orthogonal to the driver.
If you use observer to crash the driver, the problem goes away.
Needs investigation.
From the list of Helpful Guides
We need to make sure that the order of the guidelines helps the user.
scenic.ex
into getting_started
If you read the doc right now it is quite confusing to see that info before you do those steps first. Also better to keep documentation of scenic.ex
related to what the module does (supervisor stuff).scenic.ex
. This landing page will have the order of how you should read the documentation. That way we keep clean order of how to get started.So, I'm trying to build a simple little animated sprite renderer (similar to what you'd see in a game). This is done by using a sprite sheet, and by using the existing API to render.
Doing this, you call something like:
|> rect( {vp_width, vp_height},
id: :image_root,
fill: {:image, {@image_hash, 255}})
And later, if you want to be more specific, you do:
|> rect( {vp_width, vp_height},
id: :image_root,
fill: {:image, {@image_hash, start_x, start_y, image_width, image_height, theta, alpha, 255}})
(note)
Why is alpha on [0-255]
instead of just the normal [0-1]? Theta (the rotation) is in radians as it should be. We should try to make this API unsurprising for people who've done graphics. :(
(end note)
So, the problem here is that if I want to scale up my little image rectangle, I have to scale the rectangle instead of the image--the texture sample isn't automatically stretched to fit the rectangle in Scenic, which is again unexpected from normal graphics conventions.
My source image is basically this:
And when I render it with the following code (cribbed from other scenic examples and modified):
def init(_, opts) do
viewport = opts[:viewport]
IO.inspect ViewPort.info(viewport), label: "viewport info"
# calculate the transform that centers the parrot in the viewport
{:ok, %ViewPort.Status{size: {vp_width, vp_height}}} = ViewPort.info(viewport)
Scenic.Cache.File.load(@image_path, @image_hash)
graph =
@root_image_graph
|> rect( {vp_width, vp_height},
id: :image_root,
fill: {:image, {@image_hash, 0,0,100,100,0,255}})
|> group(
fn g ->
g
|> line({{-10,0},{10,0}}, stroke: {2, :magenta})
|> line({{0,-10},{0,10}}, stroke: {2, :magenta})
end,
id: :cursor_lines,
transform: {0,0})
|> push_graph()
state = %{
viewport: viewport,
graph: graph,
cursor_pos: {0,0},
in_drag: false,
start_point: nil,
end_point: nil
}
{:ok, state}
end
it renders something like this:
So, it looks like it's trying to scale the image down into a sub-rectangle which may or may not be transformed in the Scenic rectangle.
Additionally, you can kinda see image streaks: I'd suggest that that's because of an incorrect GL texture sampling mode, and that nanovg is deciding to clamp to edge. That's fine, but it's nice to be able to do other things (see glTexParameter for GL's take on this). At the least clamp to border would probably be the reasonable choice, or mirroring/repeating.
So, I'd like to propose a couple of things:
Change the image fill semantics for rectangles to stretch the entire image across the rectangle, always. There's no convenient way to, say, update the image transformation (image fill offset and scale) anyways, so we might as well just leave that up to the transform of the rectangle that is being drawn--this also means we don't have to fight with the scale
property on the rectangle at the same time we fight with the image fill's width and height.
Allow users to set the image ST scaling on the rectangle. If I have an image fill (say, a simple brick image), and I want to tile it over the rectangle right now, I can't quite do it. It'd be cool if I could specify multipliers for ST (probably better understood as X and Y tiling scaling) so that the image, once stretch over the rectangle, is scaled out (values < 1) or tiled across (values > 1) properly. This might be the time to include the ability to clamp, repeat, or mirror as seems reasonable.
(note)
The docs erroneously state the image tuple as:
{:image, {image_key, start_x, start_y, end_x, end_y, angle, alpha}}
when it should be:
{:image, {image_key, start_x, start_y, width, height, angle, alpha}}
(end note)
In light of these things, and to make the API non-breaking with what's already been done, I'd propose a new fill type:
{:image_stretched, {image_key, scale_x, scale_y, x_repeat_mode, y_repeat_mode, alpha}}
{:image_stretched, {image_key, scale_x, scale_y, x_repeat_mode, y_repeat_mode, source_offset_x, source_offset_y, source_width, source_height, angle,alpha}}
scale_x
is the S (horizontal) scale factor for the image when rendered on the rectangle. 1 is normal, 0.1 would be showing the first tenth of the horizontal parts of the image, 10 would be tiling the horizontal parts 10 times.scale_y
is the T (vertical) scale factor for the image when rendered on the rectangle. 1 is normal, 0.1 would be showing the first tenth of the vertical parts of the image, 10 would be tiling the vertical parts 10 times.x_repeat_mode
would be one of :repeat
, :clamp_to_border
, :clamp_to_edge
, :mirror
.y_repeat_mode
would be one of :repeat
, :clamp_to_border
, :clamp_to_edge
, :mirror
.source_offset_x
and source_offset_y
are the offset (in pixels) of the upper-left corner of the subset of the image to use when texturing the rectangle.source_width
is the horizontal size, in pixels, of the subset of the image to use when texturing the rectangle.source_height
is the vertical size, in pixels, of the subset of the image to use when texturing the rectangle.angle
is the CCW rotation of the image in radians prior to sampling.alpha
is the [0,1]
transparency (fully transparent to fully opaque) of the image to use.Generated my_scenic_app app
GLFW error 65543: GLX: Failed to create context: BadValue (integer parameter out of range for operation)
12:12:11.458 [error] dirty close
Elixir:
Elixir 1.7.2 (compiled with Erlang/OTP 19)
Erlang:
Erlang/OTP 21 [erts-10.0.5] [source] [64-bit] [smp:12:12] [ds:12:12:10] [async-threads:1] [hipe]
Eshell V10.0.5 (abort with ^G)
Scenic:
* parse_trans 3.2.0 (Hex package) (rebar3)
locked at 3.2.0 (parse_trans) 2adfa4da
ok
* mimerl 1.0.2 (Hex package) (rebar3)
locked at 1.0.2 (mimerl) 993f9b0e
ok
* metrics 1.0.1 (Hex package) (rebar3)
locked at 1.0.1 (metrics) 25f094de
ok
* unicode_util_compat 0.3.1 (Hex package) (rebar3)
locked at 0.3.1 (unicode_util_compat) a1f612a7
ok
* idna 5.1.2 (Hex package) (rebar3)
locked at 5.1.2 (idna) e21cb58a
ok
* gettext 0.16.0 (Hex package) (mix)
locked at 0.16.0 (gettext) 4a7e9040
ok
* ssl_verify_fun 1.1.1 (Hex package) (rebar)
locked at 1.1.1 (ssl_verify_fun) 28a4d65b
ok
* scenic_sensor 0.7.0 (Hex package) (mix)
locked at 0.7.0 (scenic_sensor) a12aed75
ok
* combine 0.10.0 (Hex package) (mix)
locked at 0.10.0 (combine) eff8224e
ok
* elixir_make 0.4.2 (Hex package) (mix)
locked at 0.4.2 (elixir_make) 332c649d
ok
* certifi 2.3.1 (Hex package) (rebar3)
locked at 2.3.1 (certifi) d0f42423
ok
* hackney 1.13.0 (Hex package) (rebar3)
locked at 1.13.0 (hackney) 24edc8cd
ok
* tzdata 0.5.19 (Hex package) (mix)
locked at 0.5.19 (tzdata) 7962a399
ok
* timex 3.3.0 (Hex package) (mix)
locked at 3.3.0 (timex) e0695aa0
ok
* scenic_math 0.7.1 (Hex package) (mix)
locked at 0.7.1 (scenic_math) 131ef7cf
ok
* scenic 0.7.0 (Hex package) (mix)
locked at 0.7.0 (scenic) fa93041f
ok
* scenic_driver_glfw 0.7.0 (Hex package) (mix)
locked at 0.7.0 (scenic_driver_glfw) e9051384
ok
* scenic_clock 0.7.0 (Hex package) (mix)
locked at 0.7.0 (scenic_clock) 645bfd0f
ok
OS:
Distributor ID: Ubuntu
Description: Ubuntu 18.04.1 LTS
Release: 18.04
Codename: bionic
Linux olafura-GS73-Stealth-8RF 4.15.0-32-generic #35-Ubuntu SMP Fri Aug 10 17:58:07 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux
sudo apt-get install pkgconf libglfw3 libglfw3-dev libglew2.0 libglew-dev
mix archive.install hex scenic_new
mix scenic.new my_scenic_app
cd my_scenic_app
mix scenic.run
Elixir:
# elixir -v
Erlang/OTP 21 [erts-10.0.7] [source] [64-bit] [smp:12:12] [ds:12:12:10] [async-threads:1] [hipe]
Elixir 1.7.4 (compiled with Erlang/OTP 21)
Erlang:
# erl -v
Erlang/OTP 21 [erts-10.0.7] [source] [64-bit] [smp:12:12] [ds:12:12:10] [async-threads:1] [hipe]
Eshell V10.0.7 (abort with ^G)
Scenic:
# mix deps | grep scenic
* scenic 0.9.0 (https://github.com/boydm/scenic.git) (mix)
* scenic_driver_glfw 0.9.0 (https://github.com/boydm/scenic_driver_glfw.git) (mix)
OS:
Arch Linux
Create a text field with many words
long_text = "a b c <etc>"
Scenic.Primitives.text(graph, long_text)
Text to wrapping to be controllable
Text wraps around 1500px all the time (but appears to wrap at a word boundary which is nice)
N/A
#106 seemed like it might be related but adding width: 100
to the text
call didn't appear to make a difference.
@boydm this will help you to maintain the project to the latest changes https://dependabot.com
It is really simple to set up. Worth to add it.
Hi there. :)
I just see this video and you say at 33:26 that Scenic has no auto-scale solution.
In the readme on this page, you say Scenic works well with my desktop
Desktops have different screen sizes.
Add optional auto-scaling.
Type specs are quite useful for understanding the data structures being used on the functions and so on.
Better to add it now than later
Many of the components are not yet documented.
If you would like to help out, as you get familiar with Scenic, please pick a module that needs documentation. Submit an issue here to claim that you are working on it, then go for it.
I will be working on as many of these (and the guides) as I can over the next few weeks. There is still quite a bit tho.
I am working on a simple game to try out scenic. Since scenic already maps an input coordinate through different translations, it would be nice if scenic was also able to accomplish collision detection. In addition to games this might be nice for developing custom responsive ui's.
Scenic.Graph.collisions(graph)
would return all the components that had a collision along with their "final" coordinates.
Of course it may be reasonable to consider this out of scope for Scenic. It may be too difficult to support permanently.
If you want to contribute to this project, probably a good first issue to solve would be reducing the number of warnings, refactoring opportunities, code readability issues, or software design suggestions reported by credo.
Now the report includes the following findings:
So, that's too much work for just one person (@boydm) to handle.
If you haven't use credo
before, you can do the following:
cd scenic
mix deps.get
mix credo
If you want to find more suggestions you can try:
mix credo --strict
For more information, please check credo project.
I noticed that the cache module doesn't have documentation, opening this issue as a notification of intent
see #5 for more details
The hashing scheme described in the docs does evaluate the paths at compile time, which is usually the development machine’s paths and not the deployed (nerves) one. That leads to a problem where fonts do no show on nerves devices, since the resource path is different.
I “fixed” it for now by differentiating a bit more and hardcoding the nerves path (bad!):
@font_hash_path :code.priv_dir(:my_app) |> Path.join("/static/fonts/myfont.otf")
if @target == "host" do
@font_path @font_hash_path
else
@font_path "/srv/erlang/lib/my_app-0.1.0/priv/static/fonts/myfont.otf"
end
@font_hash Scenic.Cache.Hash.file!(@font_hash_path, :sha)
and in init/2
def init(_, opts) do
Scenic.Cache.File.load(@font_path, @font_hash)
...
I guess thats also the problem with the built-in fonts not showing in nerves. Probably a documentation issue first and foremost.
User interaction. Allows developers to create games with Elixir + Scenic.
Accept Gamepad inputs
https://developer.mozilla.org/en-US/docs/Web/API/Gamepad_API/Using_the_Gamepad_API
https://developer.mozilla.org/en-US/docs/Web/Events/gamepadconnected
Is a decent reference.
http://html5gamepad.com/ will detect a gamepad device plugged into your computer when you press a button o n that device when on the webpage.
Is it possible to push a tag for v0.10.1 and v0.10.2? This would be useful when viewing the documentation, right now if you visit a page like: https://hexdocs.pm/scenic/Scenic.Component.Button.html and click on the view source button (in the upper right) it will bring you to a GitHub 404 page: https://github.com/boydm/scenic/blob/v0.10.2/lib/scenic/component/button.ex#L1
A scenic font should provide functionality to lookup incremental width that a character ads to a group of characters.
Should be kerning and styling aware.
Question: does height matter or is that a constant for the font.
Non goals: support for letter spacing.
This will support a number of features, notably text flow, wrapping, center positioning, and justifying.
Erlang 22.0-rc3
Elixir 1.8.0
Installed with asdf today on a Raspberry Pi 3B+
I installed @axelson 's scenic asteroids and tried running. After folliowing instructions for Ubuntu 18 dependencies and running the game, it goes into a loop. A window appears then flickers away then appears again. The terminal output is spitting rapidly.. ctrl+c interrupt.
Expected scenic_asteroids to start up
Application does not run correctly.
from ctrl+c:
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"Play.Scene.Asteroids\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\", \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\" <> ..., " (elixir) Calendar.ISO.from_unix(1221222574, :second)\n (elixir) lib/calendar/datetime.ex:118: DateTime.from_unix/3\n (msgpax) lib/msgpax/unpacker.ex:205: Msgpax.Unpacker.unpack_ext/3\n (msgpax) lib/msgpax/unpacker.ex:140: Msgpax.Unpacker.unpack/6\n (msgpax) lib/msgpax.ex:143: Msgpax.unpack_slice/2\n (msgpax) lib/msgpax.ex:213: Msgpax.unpack/2\n (font_metrics) lib/font_metrics.ex:136: FontMetrics.from_binary/1\n (scenic) lib/scenic/cache/static/font_metrics.ex:225: Scenic.Cache.Static.FontMetrics.load/3\n"}, Scenic.Scenes.Error, {{"Scenic.Scenes.Error", "%UndefinedFunctionError{arity: 2, function: :from_unix, message: nil, module: Calendar.ISO, reason: nil}", "{{\"Scenic.Scenes.Error\", \"%UndefinedFunctionError{arity: 2, function: :from_unix, message: nil, module: Calendar.ISO, reason: nil}\", \"{{\\\"Scenic.Scenes.Error\\\", \\\"%UndefinedFunctionError{arity: 2, function: :from_unix, message: nil, module: Calendar.ISO, reason: nil}\\\", \\\"{{\\\\\\\"Scenic.Scenes.Error\\\\\\\", \\\\\\\"%UndefinedFunctionError{arity: 2, function: :from_unix, message: nil, module: Calendar.ISO, reason: nil}\\\\\\\", \\\\\\\"{{\\\\\\\\\\\\\\\"Scenic.Scenes.Error\\\\\\\\\\\\\\\", \\\\\\\\\\\\\\\"%UndefinedFunctionError{arity: 2, function: :from_unix, message: nil, module: Calendar.ISO, reason: nil}\\\\\\\\\\\\\\\", \\\\\\\\\\\\\\\"{{\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"Scenic.Scenes.Error\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\", \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"%UndefinedFunctionError{arity: 2, function: :from_unix, message: nil, module: Calendar.ISO, reason: nil}\\
BREAK: (a)bort (c)ontinue (p)roc info (i)nfo (l)oaded
(v)ersion (k)ill (D)b-tables (d)istribution
Has anyone seen this occur? Scenic Asteroids is a good proof-of-concept for running a game in Scenic. The errors looked to be in Scenic/Elixir so I figured to ask here for help.
Thank you!
Elixir & Erlang:
Erlang/OTP 21 [erts-10.1.1] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [hipe] [dtrace]
Elixir 1.7.4 (compiled with Erlang/OTP 21)
Scenic:
* scenic 0.9.0 (Hex package) (mix)
locked at 0.9.0 (scenic) 129594f9
ok
* scenic_driver_glfw 0.9.1 (Hex package) (mix)
locked at 0.9.1 (scenic_driver_glfw) b64d3459
ok
OS:
MacOS10.14
mix scenic.new stest
modify home.ex as follows
mix scenic.run
defmodule Stest.Scene.Home do
use Scenic.Scene
alias Scenic.Graph
import Scenic.Primitives
import Scenic.Components
@note """
This is a very simple starter application.
If you want a more full-on example, please start from:
mix scenic.new.example
"""
@graph Graph.build(font: :roboto, font_size: 24)
|> text(@note, translate: {20, 60})
|> group(
fn g ->
g
|> text("testing", translate: {15, 250}, id: :testtxt)
|> button("hi", translate: {90, 250}, id: :testbtn)
end,
font: :roboto_mono,
font_size: 24,
id: :testgrp
)
def init(_, _) do
push_graph(@graph)
{:ok, @graph}
end
def filter_event({:click, id}, _context, graph) do
IO.inspect(graph)
IO.puts("===============")
g =
Graph.delete(graph, :testgrp)
|> IO.inspect()
|> push_graph()
{:stop, g}
end
end
Pressing the button yields an inspection of the graph before and after deleting the group.
Before:
%Scenic.Graph{
add_to: 0,
ids: %{_root_: [0], testbtn: [4], testgrp: [2], testtxt: [3]},
next_uid: 5,
primitives: %{
0 => %{
__struct__: Scenic.Primitive,
data: [1, 2],
module: Scenic.Primitive.Group,
parent_uid: -1,
styles: %{font: :roboto, font_size: 24}
},
1 => %{
__struct__: Scenic.Primitive,
data: " This is a very simple starter application.\n\n If you want a more full-on example, please start from:\n\n mix scenic.new.example\n",
module: Scenic.Primitive.Text,
parent_uid: 0,
transforms: %{translate: {20, 60}}
},
2 => %{
__struct__: Scenic.Primitive,
data: [3, 4],
id: :testgrp,
module: Scenic.Primitive.Group,
parent_uid: 0,
styles: %{font: :roboto_mono, font_size: 24}
},
3 => %{
__struct__: Scenic.Primitive,
data: "testing",
id: :testtxt,
module: Scenic.Primitive.Text,
parent_uid: 2,
transforms: %{translate: {15, 250}}
},
4 => %{
__struct__: Scenic.Primitive,
data: {Scenic.Component.Button, "hi"},
id: :testbtn,
module: Scenic.Primitive.SceneRef,
parent_uid: 2,
transforms: %{translate: {90, 250}}
}
}
}
after deletion:
%Scenic.Graph{
add_to: 0,
ids: %{_root_: [0], testbtn: [4], testtxt: [3]},
next_uid: 5,
primitives: %{
0 => %{
__struct__: Scenic.Primitive,
data: [1],
module: Scenic.Primitive.Group,
parent_uid: -1,
styles: %{font: :roboto, font_size: 24}
},
1 => %{
__struct__: Scenic.Primitive,
data: " This is a very simple starter application.\n\n If you want a more full-on example, please start from:\n\n mix scenic.new.example\n",
module: Scenic.Primitive.Text,
parent_uid: 0,
transforms: %{translate: {20, 60}}
},
3 => %{
__struct__: Scenic.Primitive,
data: "testing",
id: :testtxt,
module: Scenic.Primitive.Text,
parent_uid: 2,
transforms: %{translate: {15, 250}}
},
4 => %{
__struct__: Scenic.Primitive,
data: {Scenic.Component.Button, "hi"},
id: :testbtn,
module: Scenic.Primitive.SceneRef,
parent_uid: 2,
transforms: %{translate: {90, 250}}
}
}
}
I would expect an inspection of the graph to show that the group with id :testgroup would be removed from the graph (it is) along with its children. This is in accordance with the docs.
Children are not removed.
I can probably figure out how to fix this. I've never contributed to a github project before, so I need to figure that out.
I'm not sure if this intentional or not, but it appears as though text is rendered going up from Y, while buttons are rendered going down from Y:
I don't remember exactly what José said, but it was something about a new :build_embedded option in the mix.ex file of an application that would take care of the priv static assets without needing a Makefile to do it.
Investigate this and, if it works, replace the Makefile with the build options.
Must work on both the Desktop and Nerves versions. (thats the tricky part)
Should support word wrap, scrolling. Non-goals for initial version: RTF-like styling. Requires Issue #6
It can be confusing to new users that cursor input is not received by the root scene, yet keyboard input is. The current behavior confused me initially and has also confused others (example)
Allowing the root scene to receive any cursor input that is not captured by any other scene. I think this makes sense logically, although if it doesn't make sense for any reason than maybe it's best to just add a transparent rectangle to the example project to help people with cursor input.
Although an alternative is to educate people on the behavior of mouse input, e.g. in the scenic_new project (ScenicFramework/scenic_new#22)
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.