Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
Chunderstorm
May 9, 2010


legs crossed like a buddhist
smokin' buddha
angry tuna
Hey thread, I'm having a Unity problem that I've had before and for the life of me, I don't remember how to fix it.

I'm making a first-person camera and rotating the camera with vertical mouse movement, with its default rotation on the axis being zero. When I move the camera down, it goes from 0 to 1, but when I move up, I go from 0 to 359. How do I clamp that value between say, 45 and 300? A normal clamp keeps the camera in all the space I don't want it to go.

Adbot
ADBOT LOVES YOU

Jo
Jan 24, 2005

:allears:
Soiled Meat

Chunderstorm posted:

Hey thread, I'm having a Unity problem that I've had before and for the life of me, I don't remember how to fix it.

I'm making a first-person camera and rotating the camera with vertical mouse movement, with its default rotation on the axis being zero. When I move the camera down, it goes from 0 to 1, but when I move up, I go from 0 to 359. How do I clamp that value between say, 45 and 300? A normal clamp keeps the camera in all the space I don't want it to go.

If I'm understanding right, your camera goes from 0 to 45 and 315 to 360, and you want to snap there contiguously?

Let's say your min is 315 and your max is 45. I'm going clockwise from 0 since it's easier for me to think about it on the real plane. It's still a Pacman shape facing right. Your setup seems slightly different, but it's the same idea.

The simplest thing I can think of is...
code:
float newRotation = (cameraRotation + delta) % 360;
if(newRotation > 180) { // We're in the bottom half of the graph.
  if(newRotation < min) { newRotation = min; }
} else if(newRotation <= 180) { // We're in the top half of the graph.
  if(newRotation > max) { newRotation = max; }
}
cameraRotation = newRotation;
You might have to tweak or swap min and max.

Let's plug in some values.

We're facing right -> cameraRotation = 0. Look up 80 degrees. delta = 80. newRotation = 80.
newRotation (80) > 180? Nope.
newRotation (80) < 180? Yup.
-> newRotation (80) > max (45)? Yup.
-> newRotation = 45.

Camera gets locked to 45.

We're facing right -> cameraRotation = 0. We look down 80 degrees. delta = -80. newRotation = -80 -> 280.
newRotation (280) > 180? Yup.
newRotation (280) < min (315)? Yup.
-> newRotation = 315.

Locked to 315.

EDIT: An alternative might be to add 180 degrees to your camera angle to shift it into the correct range, then do your range check, then shift it back 180 degrees. I haven't gone through this mentally, though. It would be something like, newRotation = clamp(newRotation + 180, min + 180, max + 180) - 180.

Jo fucked around with this message at 21:03 on Jul 18, 2014

Chunderstorm
May 9, 2010


legs crossed like a buddhist
smokin' buddha
angry tuna

Jo posted:

If I'm understanding right, your camera goes from 0 to 45 and 315 to 360, and you want to snap there contiguously?

Let's say your min is 315 and your max is 45. I'm going clockwise from 0 since it's easier for me to think about it on the real plane. It's still a Pacman shape facing right. Your setup seems slightly different, but it's the same idea.

The simplest thing I can think of is...
code:
float newRotation = (cameraRotation + delta) % 360;
if(newRotation > 180) { // We're in the bottom half of the graph.
  if(newRotation < min) { newRotation = min; }
} else if(newRotation <= 180) { // We're in the top half of the graph.
  if(newRotation > max) { newRotation = max; }
}
cameraRotation = newRotation;
You might have to tweak or swap min and max.

Let's plug in some values.

We're facing right -> cameraRotation = 0. Look up 80 degrees. delta = 80. newRotation = 80.
newRotation (80) > 180? Nope.
newRotation (80) < 180? Yup.
-> newRotation (80) > max (45)? Yup.
-> newRotation = 45.

Camera gets locked to 45.

We're facing right -> cameraRotation = 0. We look down 80 degrees. delta = -80. newRotation = -80 -> 280.
newRotation (280) > 180? Yup.
newRotation (280) < min (315)? Yup.
-> newRotation = 315.

Locked to 315.

EDIT: An alternative might be to add 180 degrees to your camera angle to shift it into the correct range, then do your range check, then shift it back 180 degrees. I haven't gone through this mentally, though. It would be something like, newRotation = clamp(newRotation + 180, min + 180, max + 180) - 180.

Yeah, that was the problem. What value is delta supposed to be? I removed it because it was returning an error so the camera only locks between positive and negative 180, basically.

Thanks for the explanation, too!

e: The 2nd one didn't work. Camera ended up spazzing quite a bit.

Chunderstorm fucked around with this message at 21:42 on Jul 18, 2014

Jo
Jan 24, 2005

:allears:
Soiled Meat

Chunderstorm posted:

Yeah, that was the problem. What value is delta supposed to be? I removed it because it was returning an error so the camera only locks between positive and negative 180, basically.

Thanks for the explanation, too!

e: The 2nd one didn't work. Camera ended up spazzing quite a bit.

Delta is the amount by which you want your camera to change. You can assign it however you like, Input.mouseDelta*deltaTime, KeyDown*changeRate*timeDelta, etc. I'll check it again when I get home. The code above is really only the concept, not even the exact execution (although it might compile).

The King of Swag
Nov 10, 2005

To escape the closure,
is to become the God of Swag.

Unormal posted:

http://www.microsoft.com/bizspark/ yourself some Ultimate licenses!

Just in case anyone else signs up for Bizspark; Microsoft says you'll be approved or declined within 5 business days, but I wouldn't believe that. I signed up right after Unormal posted this (on July 2nd), and I still haven't heard a peep out of them.

FuzzySlippers
Feb 6, 2009

Me too. I've been waiting a couple weeks on Bizspark and no word.

HaB
Jan 5, 2001

What are the odds?

FuzzySlippers posted:

Me too. I've been waiting a couple weeks on Bizspark and no word.

It took about two weeks for mine, iirc. Both my original signup and the renewal.

poemdexter
Feb 18, 2005

Hooray Indie Games!

College Slice
Find your local microsoft evangelist and ask nicely. I know locally they are pushing really hard to get people signed up.

Subjunctive
Sep 12, 2006

✨sparkle and shine✨

I'm puttering around with a little map-building toy, and so far I've spent all my time on the placement and movement of rectangles. I want some simple things, I'm hoping there's some toolkit out there that's waiting to love me.

- drag rectangles from a palette of different ones
- drag rectangles from one place to another, cancelling with ESC, not allowing drag off the grid or overlapping with other buildings
- paint rectangles by dragging from corner to corner, optionally being able to overlap with buildings or other painted rects
- grouping of shapes for duplicating patterns
- super neat if I can rotate groups
- easy to label the rects

I've been playing with FabricJS, and it's OK, but I feel like I'm doing that thing where I build the engine for so long that I get sick of it before I get to the part I really care about (letting people draw out a map and then generate another format from it).

Web stuff or otherwise cross-platform stuff would be great, but failing that I'll take something that works on Windows or iOS or OS X.

roomforthetuna
Mar 22, 2005

I don't need to know anything about virii! My CUSTOM PROGRAM keeps me protected! It's not like they'll try to come in through the Internet or something!
Similar question - my latest brainwave is a turn-based grid-based puzzle game, and I'd like it to be cross-platform. I could totally do it in Unity, but I'd feel bad making something that sits there rendering the same unmoved frame over and over rapidly, running on mobile devices. Something HTML5-ey seems like it'd make more sense, where I can render to a canvas only what changes. Basically I want an interface of "I AM JUST loving BLITTING THINGS, DON'T UPDATE THE SCREEN UNLESS I SAY SO" like one would use to make games for platforms in the eighties, but I want it to be cross platform.

Is the appropriate answer to just do an HTML5 canvas game and then later cross-platform it with Intel XDK for mobiles and node-webkit for desktops? Or would maybe SDL and C++ be appropriate for this? (I see SDL has the ability to build for Android and iOS but it sounds like something that I would find frustrating.)

Also I don't really want it to be a web-game, and would hope to get it on Steam.

Also I'm fairly language-agnostic. If there's a library that would make eg. Go or Lua a language suitable for these goals, that would be okay. Anything but Python.

roomforthetuna fucked around with this message at 02:33 on Jul 20, 2014

Tendales
Mar 9, 2012

roomforthetuna posted:

Similar question - my latest brainwave is a turn-based grid-based puzzle game, and I'd like it to be cross-platform. I could totally do it in Unity, but I'd feel bad making something that sits there rendering the same unmoved frame over and over rapidly, running on mobile devices. Something HTML5-ey seems like it'd make more sense, where I can render to a canvas only what changes. Basically I want an interface of "I AM JUST loving BLITTING THINGS, DON'T UPDATE THE SCREEN UNLESS I SAY SO" like one would use to make games for platforms in the eighties, but I want it to be cross platform.

Is the appropriate answer to just do an HTML5 canvas game and then later cross-platform it with Intel XDK for mobiles and node-webkit for desktops? Or would maybe SDL and C++ be appropriate for this? (I see SDL has the ability to build for Android and iOS but it sounds like something that I would find frustrating.)

Also I don't really want it to be a web-game, and would hope to get it on Steam.

Also I'm fairly language-agnostic. If there's a library that would make eg. Go or Lua a language suitable for these goals, that would be okay. Anything but Python.

Maybe look into a language designed for cross-compiling, like Haxe? Haxe plus the Haxeflixel or Haxepunk library sounds like exactly what you're after.

Internet Janitor
May 17, 2008

"That isn't the appropriate trash receptacle."
Would your game be amenable to implementation in PuzzleScript?

roomforthetuna
Mar 22, 2005

I don't need to know anything about virii! My CUSTOM PROGRAM keeps me protected! It's not like they'll try to come in through the Internet or something!

Internet Janitor posted:

Would your game be amenable to implementation in PuzzleScript?
It could probably be prototyped there, but I'm really aiming for a polished final product (eg. tweening movement even though it's really grid-based).


Tendales posted:

Maybe look into a language designed for cross-compiling, like Haxe? Haxe plus the Haxeflixel or Haxepunk library sounds like exactly what you're after.
That looks promising. Probably not with the flixel or punk, since they're generally oriented towards a constant 30fps which is the unnecessary processor-eating I wanted to avoid from Unity, but the examples from http://derepas.com/fabrice/haxe/ suggest that just Haxe-OpenFL can do the blit-on-demand behavior that I want, and looking at one of those examples in Task Manager it's not doing anything (or at least not much) when it's idle, and uses 12% CPU when drawing rapidly. (Versus a Haxe flixel sample which uses 12% of my CPU constantly when nothing on screen is updating.) Thanks for the suggestion!

superh
Oct 10, 2007

Touching every treasure

roomforthetuna posted:

It could probably be prototyped there, but I'm really aiming for a polished final product (eg. tweening movement even though it's really grid-based).

That looks promising. Probably not with the flixel or punk, since they're generally oriented towards a constant 30fps which is the unnecessary processor-eating I wanted to avoid from Unity, but the examples from http://derepas.com/fabrice/haxe/ suggest that just Haxe-OpenFL can do the blit-on-demand behavior that I want, and looking at one of those examples in Task Manager it's not doing anything (or at least not much) when it's idle, and uses 12% CPU when drawing rapidly. (Versus a Haxe flixel sample which uses 12% of my CPU constantly when nothing on screen is updating.) Thanks for the suggestion!

A word of warning if you're getting deep into openfl, In my experience the performance of it's blitting is terrible, and too slow for an action game. For a puzzle / turn based game you could potentially be fine, but... Don't fall in love with it, it's not great.

roomforthetuna
Mar 22, 2005

I don't need to know anything about virii! My CUSTOM PROGRAM keeps me protected! It's not like they'll try to come in through the Internet or something!

superh posted:

A word of warning if you're getting deep into openfl, In my experience the performance of it's blitting is terrible, and too slow for an action game. For a puzzle / turn based game you could potentially be fine, but... Don't fall in love with it, it's not great.
What mechanism were you using? Sprites / BitmapData.copyPixels / something else? And how much stuff made it problematic?
(Just curiosity, I'd totally go back to Unity if I was doing something more actiony anyway, it just seemed a poor match for this particular game.)

Stick100
Mar 18, 2003

HaB posted:

It took about two weeks for mine, iirc. Both my original signup and the renewal.

Mine was exactly 2 weeks as well.

Stick100
Mar 18, 2003

The King of Swag posted:

Just in case anyone else signs up for Bizspark; Microsoft says you'll be approved or declined within 5 business days, but I wouldn't believe that. I signed up right after Unormal posted this (on July 2nd), and I still haven't heard a peep out of them.

Last I checked it said 10 business days. Must have some people out for summer or something.

superh
Oct 10, 2007

Touching every treasure

roomforthetuna posted:

What mechanism were you using? Sprites / BitmapData.copyPixels / something else? And how much stuff made it problematic?
(Just curiosity, I'd totally go back to Unity if I was doing something more actiony anyway, it just seemed a poor match for this particular game.)

I believe it was using BitmapData.copyPixels. It was doing a LOT of drawing, since I had a cool busted VHS filter thing going on, but it never hit the playable point. The effect worked great with just canvas context drawing. My gut tells me that OpenFL's feature parity with Flash might be holding it back.

poemdexter
Feb 18, 2005

Hooray Indie Games!

College Slice
My Bizspark took about 2 weeks (10 biz days). I'd say be patient. Even if they reject you, they'll still contact you saying so.

Afinostux
Dec 26, 2012

Anybody here have any experience figuring out opengl matrices? I've got some really strange problems that I think are a matrix thing of some kind...
I have a couple primitives being drawn at the origin, and a glulookat-like function to look at them, but I can't seem to see them unless I set use orthographic projection.

Here's what everything looks like when it's trying to draw:
code:
camera position:
vec3 (  50.000000       3.000000        50.000000  )
camera lookat:
vec3 (  0.000000        0.000000        0.000000  )
modelview matrix:
mat4
        0.707107        0.000000        -0.707107       -0.000000
        -0.029973       0.999101        -0.029973       0.000000
        0.706471        0.042388        0.706471        -70.774284
        0.000000        0.000000        0.000000        1.000000
projection matrix:
mat4
        2.747478        0.000000        0.000000        0.000000
        0.000000        2.747478        0.000000        0.000000
        0.000000        0.000000        -1.020202       -2.020202
        0.000000        0.000000        -1.000000       0.000000
the camera has a 40 degree field of view, near of 1, far of 100. If nobody can figure this one out, I'll just make the whole game with ortho projection and claim it's arty.

Actually, in addition: glVertex2f draws things I can see (only in ortho still), glVertex3f does not. Is there a thing I was supposed to turn on to make the 3d? oh god help

e: Solved it! turns out I messed up the math in the function to build the matrix, and it was looking from the lookat position to the "camera" position, instead of the other way around like it should have been. The reason the glvertex2f things were showing up and the glvertex3f weren't was because of backface culling... I'm amazed anything showed up at all

Afinostux fucked around with this message at 21:15 on Jul 21, 2014

The King of Swag
Nov 10, 2005

To escape the closure,
is to become the God of Swag.

Stick100 posted:

Last I checked it said 10 business days. Must have some people out for summer or something.

If I go to "My Bizspark", it gives me: "Your account is now pending approval. We will be in touch with you regarding your status within five business days."

Dirty
Apr 8, 2003

Ceci n'est pas un fabricant de pates

poemdexter posted:

My Bizspark took about 2 weeks (10 biz days). I'd say be patient. Even if they reject you, they'll still contact you saying so.

And, incidentally, if they do reject you, you can email to ask why. It was a slow process with their replies taking 2-5 days, but I was (just today, in fact) able to get accepted after initially getting a standard rejection email. In my case, they just needed more info from me (although I basically gave them the same information over email, and they seemed fine with it, so I dunno).

dizzywhip
Dec 23, 2005

So I have a bunch of 2D sprite sheets that I get from my artist, and I'd like to configure hitboxes and other information that syncs up with each frame. I'm using Unity's animation system, so I could theoretically use animation events for this, but that would be kind of a pain since I'd have to enter all the information textually, and it'd take a lot of trial and error to get the right values.

Are there any tools out there that'll let me load up a sprite sheet and define hitboxes visually, then export to JSON or whatever so I can load it up in the game? Maybe a Unity editor plugin? If not, is there any other decent alternative to typing out all the numbers by hand?

roomforthetuna
Mar 22, 2005

I don't need to know anything about virii! My CUSTOM PROGRAM keeps me protected! It's not like they'll try to come in through the Internet or something!

dizzywhip posted:

Are there any tools out there that'll let me load up a sprite sheet and define hitboxes visually, then export to JSON or whatever so I can load it up in the game? Maybe a Unity editor plugin? If not, is there any other decent alternative to typing out all the numbers by hand?
Unity's 2D physics collision poly editor does a reasonable job - it approximates for you based on the sprite then you can also drag things yourself. There's some malarkey with control and shift while clicking or dragging lines or points involved so it's non-obvious without the documentation.

superh
Oct 10, 2007

Touching every treasure
Either use unitys 2d sprite editor and draw the boxes yourself, or have the artist split the images out of the sprite sheet into png files and repackage them into an atlas with something like TexturePacker, which does the math for you and puts it in a data file that unity can parse.

Yodzilla
Apr 29, 2005

Now who looks even dumber?

Beef Witch
Doesn't Unity Pro have its own built-in texture atlas maker? We use TexturePacker and it works really well, just kinda curious.

But with Unity 2D stuff if you don't use atlases don't you have to make sure all of your sprites are square power of two size?

superh
Oct 10, 2007

Touching every treasure
It's got a Sprite Editor where you get to draw your own rectangles into existing Atlases. I'm not sure if it can stitch multiple pngs into atlases, though, it might! I've really only been digging into Unity 2d for a few weeks off and on, and TexturePacker was already part of my workflow, so it's what I landed on.

dupersaurus
Aug 1, 2012

Futurism was an art movement where dudes were all 'CARS ARE COOL AND THE PAST IS FOR CHUMPS. LET'S DRAW SOME CARS.'

Yodzilla posted:

Doesn't Unity Pro have its own built-in texture atlas maker? We use TexturePacker and it works really well, just kinda curious.

But with Unity 2D stuff if you don't use atlases don't you have to make sure all of your sprites are square power of two size?

NGUI has an atlas maker, and I think it uses this: http://docs.unity3d.com/ScriptReference/Texture2D.PackTextures.html

dizzywhip
Dec 23, 2005

Sorry, I think I wasn't very clear...I'm not trying to make the general collision hitboxes or figure out how to split up the sprite sheets. I'm using box colliders and the sprite editor for that already, which is working well so far.

What I'm actually trying to do is define additional hitboxes for different portions of the sprite that sync up with the animation, basically like a fighting game. So if the character punches, for example, I'd like to have a small hitbox around the character's hand for determining whether it makes contact with another character. Ideally I'd be able to have the hitbox enabled only for particular frames as well.

roomforthetuna posted:

Unity's 2D physics collision poly editor does a reasonable job - it approximates for you based on the sprite then you can also drag things yourself. There's some malarkey with control and shift while clicking or dragging lines or points involved so it's non-obvious without the documentation.

That's actually pretty much exactly what I'm looking for, but I'm not sure how to set it up so I can configure it per-frame.

poemdexter
Feb 18, 2005

Hooray Indie Games!

College Slice

Yodzilla posted:

Doesn't Unity Pro have its own built-in texture atlas maker? We use TexturePacker and it works really well, just kinda curious.

But with Unity 2D stuff if you don't use atlases don't you have to make sure all of your sprites are square power of two size?

Nope. Unity recommends that your atlas is power of 2 but your sprites can be whatever size you want.

Yodzilla
Apr 29, 2005

Now who looks even dumber?

Beef Witch
Oh weird. I thought it was required for all but maybe that's just for certain compression types.

dupersaurus
Aug 1, 2012

Futurism was an art movement where dudes were all 'CARS ARE COOL AND THE PAST IS FOR CHUMPS. LET'S DRAW SOME CARS.'
Not that it immediately relvant the current discussion, but something to add to the local knowledge pool, learned the hard way:

If you're using sprite sheets across platforms, make sure the containing texture is square. Most systems out there allow for rectangular textures, but the iOS compression method requires square textures and will make all your textures square, thus screwing up your atlas coordinates.

(This applies to NGUI's atlas maker, and hand-made stuff, at the very least. Unity2D's system may handle this for you, I don't know.)

Zaphod42
Sep 13, 2012

If there's anything more important than my ego around, I want it caught and shot now.

dupersaurus posted:

Not that it immediately relvant the current discussion, but something to add to the local knowledge pool, learned the hard way:

If you're using sprite sheets across platforms, make sure the containing texture is square. Most systems out there allow for rectangular textures, but the iOS compression method requires square textures and will make all your textures square, thus screwing up your atlas coordinates.

(This applies to NGUI's atlas maker, and hand-made stuff, at the very least. Unity2D's system may handle this for you, I don't know.)

Graphics cards also tend to want your textures not just as square, but with dimensions that are also a power of 2. Different versions of openGL or DirectX can accept different things, but its the safest way to go.

Shalinor
Jun 10, 2002

Can I buy you a rootbeer?

Zaphod42 posted:

Graphics cards also tend to want your textures not just as square, but with dimensions that are also a power of 2. Different versions of openGL or DirectX can accept different things, but its the safest way to go.
Last I checked, this was particularly an issue on embedded cards (Intel). Most high end cards don't outright barf at non-pow-2 textures anymore, but there's literally almost never a reason to not use them regardless. Just pad your stuff out and use a compressed texture format (DXT, etc, unity handles it for you), and it won't even affect your memory footprint in most cases.

Generally, anything you'd legit want a non-pow-2 for? Is something you should be texture atlasing instead. UI elements and 2D hand-animated sprites being the usuals.

Suspicious Dish
Sep 24, 2011

2020 is the year of linux on the desktop, bro
Fun Shoe
Atlassing is a dumb hack and you can get artifacts by sampling outside the bounds of the texture. Use a texture array. Even better if you can use a bindless texture, so to the hardware, it's just sampling from an arbitrary pointer in vram.

Subjunctive
Sep 12, 2006

✨sparkle and shine✨

Shalinor posted:

Generally, anything you'd legit want a non-pow-2 for? Is something you should be texture atlasing instead. UI elements and 2D hand-animated sprites being the usuals.

Render-to-texture is the most common NPOT usage, I think.

One Eye Open
Sep 19, 2006
Am I awake?

Suspicious Dish posted:

Atlassing is a dumb hack and you can get artifacts by sampling outside the bounds of the texture. Use a texture array. Even better if you can use a bindless texture, so to the hardware, it's just sampling from an arbitrary pointer in vram.

Texture arrays are an OpenGL ES 3.0 feature, so if you're targeting mobile, you're excluding a large proportion(still a majority, uptake-wise, AFAIK) of your users who are still on ES 2.0.

The King of Swag
Nov 10, 2005

To escape the closure,
is to become the God of Swag.

One Eye Open posted:

Texture arrays are an OpenGL ES 3.0 feature, so if you're targeting mobile, you're excluding a large proportion(still a majority, uptake-wise, AFAIK) of your users who are still on ES 2.0.

It's also not supported in DirectX 9, which is still the primary render target for indie desktop games, and a lot of open source game engines.

In other news, my first Unity Asset Store asset has just been approved, and it's free to boot!

Fuzzy Logic - A minimal yet robust fuzzy logic library for floating point numbers.

I needed the majority of the functionality for that unit conversion library I'm working on (and was getting help with in this thread, the other week), and I realized that I was so close to having another small library of its own, that I decided to go ahead and flesh it out, and then release it for free. It doesn't actually rely on anything Unity related, so here's the generic repo for it. Obviously it's written in C# and not UnityScript or Boo.

Suspicious Dish
Sep 24, 2011

2020 is the year of linux on the desktop, bro
Fun Shoe

One Eye Open posted:

Texture arrays are an OpenGL ES 3.0 feature, so if you're targeting mobile, you're excluding a large proportion(still a majority, uptake-wise, AFAIK) of your users who are still on ES 2.0.

If you're on mobile, expect literally nothing to work because GL drivers are trash.

Adbot
ADBOT LOVES YOU

superh
Oct 10, 2007

Touching every treasure
I can't imagine texture arrays work in an html canvas context either? Texture atlases are still a commonly useful standard. You don't get edge bleed if you put a few pixels of padding in between your source images.

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply