RMRK is retiring.
Registration is disabled. The site will remain online, but eventually become a read-only archive. More information.

RMRK.net has nothing to do with Blockchains, Cryptocurrency or NFTs. We have been around since the early 2000s, but there is a new group using the RMRK name that deals with those things. We have nothing to do with them.
NFTs are a scam, and if somebody is trying to persuade you to buy or invest in crypto/blockchain/NFT content, please turn them down and save your money. See this video for more information.
[VX]Text in Window issue

0 Members and 1 Guest are viewing this topic.

***
Rep:
Level 75
What the...?
So I've created a window.  In a window, I know you can use the following line to draw text:

self.contents.draw_text(x, y, width, height, alignment)

I have no problem with that and I've used it a bunch of times.  My problem comes when I want to display text on MULTIPLE lines.  I thought maybe
it was as simple as placing a \n at the end of lines to make it jump to the new line, but apparently, that only shows a little box.  So, I'm wondering how to make this happen.  Even if I change the width and height in the line above to accomadate the paragraph, it all ends up being squeezed into a single line of text.  I've been doing some searching on a few sites, but I'm unable to come up with the solution. 

Any help would be greatly appreciated.  Even if it's just a link to learn for myself.  That's cool, too.
« Last Edit: December 11, 2012, 07:04:29 PM by IXFURU »

**
Rep:
Level 66
RMRK Junior
Here's a quick script I wrote to allow you to use \n in draw_text:

Code: [Select]
class Bitmap
  alias tdks_mline_draw_text draw_text
  def draw_text(*args)
    if args[0].is_a?(Rect)
      args[0..0] = [args[0].x, args[0].y, args[0].width, args[0].height]
    end
    text = args[4].split(/[\n\r]/)
    y = args[1]
    text.each { |ln|
      args[1] = y
      args[4] = ln
      tdks_mline_draw_text(*args)
      y += text_size(ln).height
    }
  end
end

It should work.

***
Rep:
Level 75
What the...?
Hey this will be cool if you can get it to work.  I get an error on this line:

Code: [Select]
   text = args[4].split(/[\n\r]/)

Private Method 'split' called for fixnum

I got a question, just the same.  Why does the \n notation not work in Windows?

***
Rep:
Level 70
RMRK Junior
No clue if this will work...

text = args[4]
text = text.split(/[\r\n]/)
Heretic's Vehicles XP (Boat and Magic Carpet)

Heretic's Collection XP Ver 2.3 - Updated to include Dynamic Lighting, Moving Platforms, Vehicles, and much much more!

*
Rep:
Level 82
Hey this will be cool if you can get it to work.  I get an error on this line:

Code: [Select]
   text = args[4].split(/[\n\r]/)

Private Method 'split' called for fixnum

I got a question, just the same.  Why does the \n notation not work in Windows?

It's not so much a case of not working in Windows (it works for me if I use it on a console window with C++). RPG Maker even uses it itself:

Code: [Select]
 
  #--------------------------------------------------------------------------
  # * Get All Text Including New Lines
  #--------------------------------------------------------------------------
  def all_text
    @texts.inject("") {|r, text| r += text + "\n" }
  end

The draw_text method creates a bitmap of that length and width with the text written into it. It's likely that it doesn't do formatting and checks for \n before it applies the text to the bitmap. Which is why you need to add that in manually.

The reason you are getting an issue is because args[4] is apparently a Fixnum object and Fixnum does not have a method called #split. Check what you are sending to draw_text, make sure it is a string that is being passed in and not a number.

It's interesting that you get a private access error, though. That happens because you can only call a private method from within the class itself, not through an instanced object. A quick look doesn't turn up #split as a method of any kind in Fixnum.

Unless you have some other scripts that are messing with the class and causing this problem.

(Why do I always feel like it's the end of the world and I'm the last man standing?)

***
Rep:
Level 75
What the...?
Quote
It's not so much a case of not working in Windows (it works for me if I use it on a console window with C++). RPG Maker even uses it itself:

I shouldn't have capitalized "Windows".   :-\ It led you to believe I was talking about the Microsoft Product.  What I was really asking was why doesn't it work in RPGMakerVX windows. 

At any rate, can you explain a little about the def all_text method you suggested there?  For instance, I can't find the method "inject" by searching the help files.  What does it do exactly?

What I think it does at a glance is for every "\n" that is found, it replaces it with "".   Not sure if that is right.  And where should I call this method, just before the draw_text method is called with the text?  Maybe I could send an argument of the string into the method. 

Code: [Select]
def get_all_text(my_argument)
     my_argument.inject........and so on


Quote
The reason you are getting an issue is because args[4] is apparently a Fixnum object and Fixnum does not have a method called #split. Check what you are sending to draw_text, make sure it is a string that is being passed in and not a number.

I will recheck this.  The information is held in a constant variable hash.   Perhaps I omitted the '[x]' part and it was just returning a key.




**
Rep:
Level 66
RMRK Junior
So, without further inconvenience, let's clean this all up, shall we? You know that you can't use Regexp in this case whatsoever, since the Bitmap class has no idea what a 'new line' is. So, here it goes; Use the symbol "\ln" in case you want the text to be drawn on a 'new line', or it'll do it automatically for you if the text-width goes outside the Bitmap box.
Code: [Select]
class Bitmap
 
  def slice_text(x, y, width, height, text)
    words = text.split
    result, current_text = [], words.shift
    words.each_index {|i|
      if current_text.sub!(/\ln/) { '' } != nil ||
        self.text_size("#{current_text} #{words[i]}").width > width
        result.push(current_text)
        current_text = words[i]
      else
        current_text = "#{current_text} #{words[i]}"
      end
      result.push(current_text) if i >= words.size-1
    }
    result.each_index { |i|
      draw_text(x, y + (height * i), width, height, result[i])
    }
  end
end

***
Rep:
Level 75
What the...?
So just so I'm clear on this, Mangomight:

I just replace the draw_text line with a call to the slice method you created?
And for x, y, width, height, I just use the same values?  Like I was using the draw_text method?

*
Rep:
Level 82
My mistake on the "Windows" thing. I was confused to begin with.

Spoiler for inject:
#inject is a method that was introduced to Ruby in a later version than that used by RMVX. I wasn't too sure which version you were using, but I do now. You won't find #inject in VX, though you could add it in yourself. It makes it easier to do accumulated iterations of an enumerable object.

I'm not too great at explaining things sometimes, and #inject happens to be one of those. I know what it does, and how it works, but I get to a point in explaining it where I'm unsure if I'll cause confusion. So instead, I'll point you to here:

http://blog.jayfields.com/2008/03/ruby-inject.html

Because that explains it quite well.

For some examples, which might lead to your making your own understanding:

Code: [Select]
numbers = [1, 2, 3, 4, 5]
sum = numbers.inject { |result, n| result += n } #gets the sum of all numbers
p sum     # 15

sum_with_initial_value = numbers.inject(8) { |result, n| result += n } #sum of all numbers, with initial value of 8.
p sum     # 23  (8 + [sum of all numbers] )

product_of_all = numbers.inject { |result, n| result *= n } #product of all numbers
p product_of_all    # 120  (1 x 2 x 3 x 4 x 5 = 120)

letters = ['a', 'b', 'c', 'd', 'e']
string = letters.inject { |result, s| result += s }
p string    # "abcde"

string_with_spaces = letters.inject("") { |result, s| result += s + " " }
p string_with_spaces = "a b c d e "

The last one looks a bit like that method I showed you.

Code: [Select]
texts = ["Some line one", "Some line two", "Some line three"]
as_string = texts.inject("") { |r, text| r += text + "\n" }

The result of as_string we would see is:

Code: [Select]
p as_string  # "Some line one\nSome line two\nSome line three\n"

So the effect of all_text is to combine an array of strings into one string, those original strings now separated by a new line escape character.

Hopefully you can get some understanding about it. It is a VX Ace thing, unless you write the method implementation into the Enumerable module in VX. So it won't be too useful for you, but sometimes it's nice to learn about something new.

On another note, thanks Mangomight for the code there. You can use it instead of draw_text when you want text on multiple lines on a given bitmap. The same values can be used for either. The difference is that slice_text is needed when you want the \ln formatting to be considered (using draw_text in this case will show up those \ln rather than go onto a new line).

I have an observation, though. There's no means of setting the alignment of the strings. I wouldn't expect to be able to set the alignment of each individual string, but an option to set to the left, center or right would be nice to retain.
(Why do I always feel like it's the end of the world and I'm the last man standing?)

***
Rep:
Level 75
What the...?
Thanks for that, LoganF.   I will check out the link you provided.  I haven't gotten Ace just yet.  As I was really late getting into scripting, I have just got bearings in the VX format.   

I tried Mangomight's method.  It still cuts the words off the right hand side of the box and DOESN'T return to the next line.  I also tried Thallion Darkshine's aliased draw_text method.  And I get the Fixnum PRivate Method Error.  I was told to make sure I was passing in a string and not a fixed number, and the thing is, the error occurs when as the game is just starting, Well before the scene is even called.  I think this is because BitMap class is called before the actual game start.   

Anyway, I think maybe there's some confusion of what I'm searching for here.  I'm not real good at explaining things either.  So I'll try to clear things up a little.

I want to be able to draw a long paragraph on the bitmap.  I have it set up like this:

Code: [Select]
  ENTRIES = {#<<<Don't delete this!
 
 
  #---------------------HISTORY TOPICS------------------------------------------
  0 => "This will be about lands and nations.\n  It will be important to see if this can be written\n on two or more lines. You see?",
  1 => "This will be about historical events",
  2 => "This will be about current affairs",
  3 => "This will be about people and classes",
  4 => "This will be about world artifacts",

}

In that constant, I'm setting up what will be visibly displayed as text when the player selects a specific topic of interest.  So, I get the correct hash key in the script and send it to a method which takes the text from the key and displays it.  It's part of the particular window's refresh method:

Code: [Select]
  def refresh
    self.contents.clear
    self.contents.font.size = 14   
    self.contents.font.color = text_color(TOPIC_HEADING_COLOR)
    self.contents.draw_text(-16, 0, self.width, WLH, @heading, 1)
    self.contents.font.size = 12   
    self.contents.font.color = normal_color
    self.contents.draw_text(-16, WLH * 2, self.width, WLH, @entry, 1)
  end

Using the method above, it simply shrinks the text down to fit.  Which causes it to be unreadable.  Mangomight's method, didn't shrink the text, but still ended up drawing it with some of the text running off the side.   If bitmap class can't recognize backslash notation, then I just want it to know to place the stuff on different lines.

So that's how it all is supposed to work.  I actually got it to work using ModernAlgebra's ParagraphFormatter.   But that's the only way it's exactly right.

I really appreciate all the help I'm getting here.  And I'll be sure to give credit if I can ever get it to work.   


*
Rep:
Level 82
I'm assuming that you are trying to learn how to do this yourself, rather than utilize other's scripts?

Paragraph Formatter is so useful, that it can take away the need to write your own version (programmer's are lazy and when someone else has done it, that's perfect for them). Trying to understand an existing script can be a little difficult but is a good way to do it.

If you need a bit of assistance in understanding how it works and, in particular, what Formatter and Artist does, I can do that too. It might not be perfect, but it should be accurate enough to let you do something similar, or at the least give you some understanding.

For your actual project, though, I'd still stick to Paragraph Formatter as the actual thing that you use. The reason being that it works, for one thing, and it's a well written script that let's you do what you want without having to write a lot of code all the time.
(Why do I always feel like it's the end of the world and I'm the last man standing?)

***
Rep:
Level 75
What the...?
Quote
I'm assuming that you are trying to learn how to do this yourself, rather than utilize other's scripts?

Yes.  I'd rather do for myself.  But I'm kind of stumped when it comes to tearing apart and piecing together strings in any large scale.  I can do simple things, and I'm learning RegExp, but some things still go over my head pretty easily.


Quote
Paragraph Formatter is so useful, that it can take away the need to write your own version (programmer's are lazy and when someone else has done it, that's perfect for them). Trying to understand an existing script can be a little difficult but is a good way to do it.


I'm in total agreement.  The Formatter is simple to use and does a great job at producing the result I want.  Just need the okay from MA on that.  Not sure if it's cool to just say 'this script requires that script' without his consent.  I hope it works out, because I'm only days away from completing this script. 

I'm having another problem with the same script you may be able to help with.  It's the final bug in the system.  I'll just explain it, and if you wanna tackle it, you can.  It's probably better that I don't open another thread anyway.  If not, I'll see if I can't manage on my own.



Spoiler for "Beware, this is unrelated to the issue at hand":
I'm having an issue drawing options of a selectable window.  Some options show up, while others do not.  The cursor moves properly.  The various things in the other windows change properly, dependent upon which one you are highlighting, but any selection which isn't drawn on the window when it is first drawn, doesn't show up.  By that I mean that if you have to scroll down to find more options, the options there are invisible.  Any idea what may cause something like that?  I've been reading into the Window Selectable default script.  And I've been looking into the items, shops and skills window scripts, as I know they have scrollable selectables, but thus far, I'm not able to pinpoint exactly what is responsible for drawing 'hidden' text outside the scope of the window.   Hope that makes sense.


*
Rep:
Level 82
I'm in total agreement.  The Formatter is simple to use and does a great job at producing the result I want.  Just need the okay from MA on that.  Not sure if it's cool to just say 'this script requires that script' without his consent.  I hope it works out, because I'm only days away from completing this script. 

That's what the script is there for. I am pretty sure that if you provide the relevant credit, he will be good with that. It's a scripting utility script, so it's designed to be used in this way. Getting his consent is always a nice thing to do, though, as it means he can know personally that his script is being useful to someone else.


Spoiler for Regarding your other issue::
Whenever I'm working with selectable options, I always end up running into that same issue. And each time it stumps me for a little while. I can't be sure, but I think it has something to do with refreshing the list of options. if you can post up the script, or send it me via PM if you want to keep it secret a little longer I can look at it better. It's in my head what is happening, but I cannot remember for the life of me.
(Why do I always feel like it's the end of the world and I'm the last man standing?)

***
Rep:
Level 75
What the...?
I sent it to you, LoganF.