Save-Point
FXRuby thread - Printable Version

+- Save-Point (https://www.save-point.org)
+-- Forum: Official Area (https://www.save-point.org/forum-3.html)
+--- Forum: Tech Talk (https://www.save-point.org/forum-87.html)
+--- Thread: FXRuby thread (/thread-8427.html)



FXRuby thread - Kain Nobel - 12-22-2021

Hello everybody,

I no longer have Qt so I'm messing with GUI building applications that are Ruby based. While I do have multiple (experimental prototype) projects in different toolkits (tk, Shoes, TGUI (SFML)), this thread will focus exclusively on FXRuby and whatever related problems I come across.

So right now I'm trying to create an expanded system for Animation effects (think RMVX Ace Database/Animations + some extra features).

The problem I'm having is I can't figure out how to dynamically set dimensions of various widgets such as FXImageView, FXButton, FX... whatever. For some reason, FXMainWindow responds to #width=, #height=, #resize(width, height) but none of the other classes seem to respond to these functions. I would like to micromanage the width and height of all the widgets (buttons, image view, etc) in this frame and ensure that they don't auto-morph. Matter of fact, I'd like the size of the window to not be mouse-adjustable either, I'd like it fixed. I'm understanding that this system does a lot of auto-formatting but sometimes I just want something to be exactly where I want it (x, y) at the exact size I want (width, height).

To install FXRuby do gem install fxruby. This is NOT an RPG Maker script, so Ruby is required to run it.
 
The const ANIMATION_PNG will have to be changed to something on your computer so we have a png graphic to work with.

Code:
#================================================================================
# * DBAnimations : Require/Include
#================================================================================

require 'fox16'

include Fox

#================================================================================
# ** DBAnimations
#================================================================================

class DBAnimations < FXMainWindow
  #------------------------------------------------------------------------------
  # * Constant Variable Declarations
  #------------------------------------------------------------------------------
  APP_PNG  = ''
  ICON_PNG = 'C:/RMXP/Kain Nobel/Graphics/Icons/zsword.png'
  ANIMATION_PNG = 'C:/RMXP/Kain Nobel/Graphics/Animations/Explosive03.png'
  #------------------------------------------------------------------------------
  # * Public Instance Variables
  #------------------------------------------------------------------------------
  attr_reader :panel1
  attr_reader :panel2
  attr_reader :panel3
  attr_reader :panel4
  attr_reader :panel5
  attr_reader :list
  attr_reader :button_prev
  attr_reader :button_next
  #------------------------------------------------------------------------------
  # * Object Initialization
  #------------------------------------------------------------------------------
  def initialize(app)
    @app_data = app
    super(app, "DB::Animations", nil, :width => 800, :height => 600)
# Set application icon
set_application_icon
# Create data
create_data
# Create general settings panel
create_panel1
# Create effects panel
create_panel2
# Create frames panel
create_panel3
# Create animation viewport
create_animation_viewport
# Create buttons panel
create_panel4
# Create frames viewport
create_frames_viewport
  end
  #------------------------------------------------------------------------------
  # * Set Application Icon
  #------------------------------------------------------------------------------
  def set_application_icon
    # ...
  end
  #------------------------------------------------------------------------------
  # * Create data
  #------------------------------------------------------------------------------
  def create_data
    @icon_png = ICON_PNG
@animation_png = ANIMATION_PNG
@intTarget = FXDataTarget.new(10)
  end
  #------------------------------------------------------------------------------
  # * Create Panel 1
  #------------------------------------------------------------------------------
  def create_panel1
    # Create panel 1
    @panel1 = FXHorizontalFrame.new(self,
  LAYOUT_SIDE_TOP|FRAME_THICK|LAYOUT_FILL_X)
# Fill in left side
    create_panel1_left
# Fill in right side
create_panel1_right
  end
  #------------------------------------------------------------------------------
  # * Create Panel 1 Left
  #------------------------------------------------------------------------------
  def create_panel1_left
    # Create group box
group = FXGroupBox.new(@panel1, "General Settings",
:opts => GROUPBOX_NORMAL|FRAME_GROOVE)
# Make "Name" label
label1 = FXLabel.new(group, 'Animation Name')
# Make "Name" text field
@write_name = FXTextField.new(group, 1, :width => 240, :padLeft => 40,
  :padRight => 40)
@write_name.text = 'Explosion 3'
# Make "Graphics" label
label2 = FXLabel.new(group, 'Graphics')
# Make "Graphics" text fields (x2)
@write_graphics1 = FXTextField.new(group, 1, :width => 240, :padLeft => 40,
  :padRight => 40)
@write_graphics2 = FXTextField.new(group, 1, :width => 240, :padLeft => 40,
  :padRight => 40)
# Make "Position" label
label3 = FXLabel.new(group, 'Position')
# Make "Position" combo box
@combo_position = FXComboBox.new(group, 1, :opts => COMBOBOX_NORMAL)
@combo_position.fillItems(['Top', 'Center', 'Bottom'])
# Make "Max Frame #" label
label4 = FXLabel.new(group, 'Max #')
# Make "Max Frame #" spinner
    @spinner = FXSpinner.new(group, 5, @intTarget, FXDataTarget::ID_VALUE,
      SPIN_CYCLIC|FRAME_SUNKEN|FRAME_THICK|LAYOUT_CENTER_Y|LAYOUT_FILL_ROW)
@spinner.range = (1..400)
  end
  #------------------------------------------------------------------------------
  # * Create Panel 1 Right
  #------------------------------------------------------------------------------
  def create_panel1_right
    # Create group box
group = FXGroupBox.new(@panel1, "Effects Timing",
:opts => GROUPBOX_NORMAL|FRAME_GROOVE|LAYOUT_FILL_X|LAYOUT_FILL_Y)
# Create table for effects data
@table = FXTable.new(group, nil,
  :opts => FRAME_GROOVE|LAYOUT_FILL_X|LAYOUT_FILL_Y)
  end
  #------------------------------------------------------------------------------
  # * Create Panel 2
  #------------------------------------------------------------------------------
  def create_panel2
    @panel2 = FXVerticalFrame.new(self,
  LAYOUT_SIDE_RIGHT|FRAME_THICK|PACK_UNIFORM_WIDTH)
@button01 = FXButton.new(@panel2, 'Change Target...', nil, nil, 0, BUTTON_NORMAL)
@button02 = FXButton.new(@panel2, 'Paste Last', nil, nil, 0, BUTTON_NORMAL)
@button03 = FXButton.new(@panel2, 'Copy Frames', nil, nil, 0, BUTTON_NORMAL)
@button04 = FXButton.new(@panel2, 'Clear Frames', nil, nil, 0, BUTTON_NORMAL)
@button05 = FXButton.new(@panel2, 'Tweening', nil, nil, 0, BUTTON_NORMAL)
@button06 = FXButton.new(@panel2, 'Cell Batch', nil, nil, 0, BUTTON_NORMAL)
@button07 = FXButton.new(@panel2, 'Entire Slide', nil, nil, 0, BUTTON_NORMAL)
@button08 = FXButton.new(@panel2, 'Play (Hit)', nil, nil, 0, BUTTON_NORMAL)
@button09 = FXButton.new(@panel2, 'Play (Miss)', nil, nil, 0, BUTTON_NORMAL)
@button10 = FXButton.new(@panel2, 'Play (Critical)', nil, nil, 0, BUTTON_NORMAL)
  end
  #------------------------------------------------------------------------------
  # * Create Panel 3
  #------------------------------------------------------------------------------
  def create_panel3
    # Create the first panel
    @panel3 = FXVerticalFrame.new(self,
      LAYOUT_SIDE_LEFT|FRAME_THICK|PACK_UNIFORM_WIDTH)#,
      #:padLeft => 40, :padRight => 40, :padTop => 20, :padBottom => 20)
# Set panel width
@panel3.width = 240 # <-- NOTE : Width doesn't change...
# Create "PREV" button
@button_prev = FXButton.new(@panel3, '-BACK-', nil, nil, 0, BUTTON_NORMAL)
# Create Frame List
composite = FXComposite.new(@panel3, FRAME_THICK)
@list = FXList.new(@panel3, nil, 0, FRAME_THICK, :width => 240, :height => 480)

# Resize list
#@list.width = 240 # <-- NOTE : Width doesn't change...
#@list.height = 480 # <-- NOTE : Width doesn't change...
@list.resize(240, 480) # <-- NOTE : Doesn't resize

# Fill list with frames
items = []
(1..10).each do |item|
  n = sprintf("%02d", item)
  items << "Frame #{n}"
end
@list.fillItems(items)

# Create "NEXT" button
@button_next = FXButton.new(@panel3, '-NEXT-', nil, nil, 0, BUTTON_NORMAL)
  end
  #------------------------------------------------------------------------------
  # * Create Panel 4
  #------------------------------------------------------------------------------
  def create_panel4
    @panel4 = FXHorizontalFrame.new(self,
  LAYOUT_SIDE_TOP|FRAME_THICK|LAYOUT_FILL_X)
  end
  #------------------------------------------------------------------------------
  # * Create Animation Viewport
  #------------------------------------------------------------------------------
  def create_animation_viewport
    # ...
  end
  #------------------------------------------------------------------------------
  # * Create Frames Viewport
  #------------------------------------------------------------------------------
  def create_frames_viewport
# Load whole animation image
image = FXPNGImage.new(app, open(@animation_png, 'rb').read, 0, 960, 192)
image.scale(image.width / 2, image.height / 2)
#image.render
# Send animation image to viewer
#@image = FXImageView.new(@panel3, image, nil, 0, 0, 0, 0, 480, 96)
@image = FXImageView.new(@panel4, image,
:opts => FRAME_THICK|LAYOUT_SIDE_BOTTOM|PACK_UNIFORM_WIDTH, :width => 480)
#@image = FXImageFrame.new(@panel3, image, :opts => FRAME_SUNKEN)#, :width => 480,
#:height => 96)
@image.height = 96
  end
  #------------------------------------------------------------------------------
  # * Create
  #------------------------------------------------------------------------------
  def create
    super
    show(PLACEMENT_SCREEN)
  end
end

#================================================================================
# ** Main Processing
#================================================================================
begin
if __FILE__ == $0
  FXApp.new do |app|
    p(app)
    DBAnimations.new(app)
    app.create
    app.run
  end
end
rescue Exception => e
  p(e.message)
  system("PAUSE")
end

Things I'm trying to figure out...
  • Change the X, Y, Width and Height of different widgets to desired dimensions.
  • Make FXMainWindow a fixed size. No full screen, no adjusting with mouse.
  • Set a designated application icon.
  • Figure out how to format the table's columns and rows for future use.

Here is an image of what the application currently looks like (WIP). The formatting isn't the greatest, I need to work out all the kinks to make it look prettier.

[Image: DBAnimation.png]

EDIT: I've updated the code in the post and (here) is a pastebin link if the formatting messes up. IRB still acts like a fool sometimes with error exceptions but I'll figure out a more robust solution later on.

I'm waiting for the "FXRuby : Create Lean and Mean GUIs With Ruby" book to arrive. Until then, I'm just messing with examples and trying to make what I need right away.

So what would usually be considered the "SE and Flash Timing" table, I was going to introduce all of the sprite effects that are already programmed into the Sprite classes, such as appear, vanish, blink, collapse, etc. I also want to trigger Damage Pop (Whole) and Damage Pop (Frac) via the sub-prompt to allow for fine tuned control of damage display. There is a lot more but needless to say this will replace (or extend) the default RPG Maker animation file system with something chunkier and meatier.


RE: FXRuby thread - Kain Nobel - 12-22-2021

I shouldn't even be awake right now, nor should I be bumping this but I've made significant progress. I'm still trying to figure out how to format things the way I want them but here is the latest format...

(Things aren't correctly placed exactly as I want them, some stuff is missing, but this is a work in progress)

[Image: DBAnimation.png]

If I get comfortable working with this software, I might re-start the ReGaL project. No promises. I have a business to run and life is busy, but I would still like to get back into it. If anything, I'll at least try to finish this widget and I'm sure people could use it to extend their RPG Maker stuff. I don't think the widgets will need to run on the same version of Ruby as RM, nor will anybody need to require the Ruby Gem within their project. We'll see...


RE: FXRuby thread - kyonides - 01-01-2022

I'm sorry to tell you something you might have learned on your own, Kain, but it seems that the Fox Toolkit philosophy behind windows and its components (buttons, boxes, etc.) promotes their adaptability instead of their rigidness. Sad

Plus the contents actually look quite weird if running on Debian, a Linux OS that supports Ruby 2.7 and fxruby 1.6.x. Happy with a sweat


RE: FXRuby thread - Kain Nobel - 01-24-2022

What do the contents actually look like running on Debian? I've tried to look up screenshots to see what you're talking about but I don't know enough about Debian; if Debian was a criminal in a lineup, I'd probably be thrown off by their COVID mask haha. Due to limited resources, I might stick with the FXRuby even if its not cosmetically the sexiest model on the runway. I've developed the most widgets with it in the quickest amount of time thus far, and these are the most functional thus far, so it would be hard to back out of using it.

With FXRuby running in C++ I'm interested in extending Ruby with C++. I had to put the Database/Animation widget on hold to implement an Audio module.