3D text default values


#1

I need to create 3D text in a script. Is there anyway to get the users default values that appear in the 3D text dialog box? This would be font name, height, justification etc… I don’t really want to read the registry if I can avoid it. This needs to work on Windows and on Mac


#2


entities.add_3d_text('test', TextAlignLeft, "Arial", true, false, 1.0, 0.0, 0.5, true, 5.0)

The minimum values to pass are the first three:
string = The text to create.
alignment = Number that defines the alignment. There are constants called TextAlignLeft, TextAlignRight, and TextAlignCenter that can be passed.
font = String font name.

‘font’ can be ‘’ on PC an uses the default Arial [I think?], but passing an non-existent font-name will probably crash a MAC.

Unfortunately most of the others default to the system default, NOT the user’s current settings, so e.g. the height defaults to 1" and the thickness is 0.0

So I think you’ll need to get the Registry entries…
HKEY_CURRENT_USER\SOFTWARE\SketchUp\SketchUp 2017\ThreeDText
and read the various values:

require 'win32/registry'
values = {}
Win32::Registry::HKEY_CURRENT_USER.open('SOFTWARE\SketchUp\SketchUp 2017\ThreeDText'){|reg|
  reg.each_value{|name, type, data| values[name] =  data }
}
p values
{"FaceName"=>"Arial", "Bold"=>0, "Italic"=>0, "Height"=>"0.984252", "Align"=>0, "Filled"=>1, "Extruded"=>0, "Extrusion"=>"0.000000"}

You’ll need to change some value ‘types’ from string to float etc -
e,g. height = values['Height'].to_f and extrusion = values['Extrusion'].to_f
And the various Boolean values - 0/1 to false/true etc…

On MAC you’ll need to interrogate the plist…


#3

So then the short answer is there isn’t a way other than the registry or plist that anyone knows.

I would suspect that Sketchup doesn’t go to the registry each and every time the user wants to add 3D text within a session.


#4

the problem with reading defaults is if I last used it for 1.5m heigh letters in a particular font and I’m now building a 1:1 staircase…

> `defaults read com.sketchup.SketchUp.2017 ThreeDText`
{
    Align = 2;
    Bold = 0;
    Extruded = 0;
    Extrusion = 0;
    FaceName = "Geeza Pro";
    Filled = 1;
    Height = "39.37007904052734";
    Italic = 0;
}

john


#5

Exactly. SketchUp loads defaults at startup, and writes them only at shutdown. In the interim it uses internal collection of settings that have not yet been exposed to the APIs.

CORRECTION: SketchUp loads defaults at startup, and writes MOST OF them only at shutdown. There are some settings that are written dynamically. (See post 8 below for result of test showing 3DText settings are written immediately after tool use.) However, be careful, as settings are seldom read dynamically from the registry. So, directly changing the settings, in the registry whilst SketchUp is running, will not work. SketchUp does not watch for these kinds of changes.


I’ve asked some years ago for an application level (ie, Sketchup.options)
OptionsManager instance, so we can at least read the user’s settings. (But it may not have been translated into a formal Feature Request.)

It has not yet been given to us. (They’ve been concentrating on getting the new C APIs up to parity, before adding much of anything new.)

Some things, that just couldn’t wait, have instead been implemented in new little modules.
Example: Sketchup::RegionalSettings

At least 2 years ago, I mentioned an application level OptionsManager instance, but it was in a comment attached to another FR concerning the registration of resource paths. (Which they’ve decided not to do, as yet, … instead just revamping where the default resource folders are located.)

@tt_su, Can you please, check if a API FR has been logged re, a read-only application level OptionsManager instance ?
(I do remember a long time ago, logging a feature for you concerning reading the user’s ClickStyle setting.)


#6

I think I’ll store what I need in my own ini file which can be accessed by Windows or Mac with the exact same code. This allows plugin specific fonts and sizes.


#7

You can use Sketchup::read_default and Sketchup::write_default as a cross-platform solution for your extensions.

It is suggested that the keys be qualified just as you would your plugin namespace and attribute dictionaries (replacing teh scope operator :: with an underscore.) Ie:
Company_PluginName

But this all is a different animal from getting the application’s defaults.


#8

Checking the registry on Windows (SUv2016) the “ThreeDText” key does not even exist if the user has not yet used the tool for that particular SketchUp install.

Now I just used the 3DTextTool, for the first time in this clean install of v2016, and then refreshed the Registry Editor view, and Viola! SketchUp immediately writes the settings under the new keys “ThreeDText” and “ThreeDTextDlg”.

… Now I just used it a second time (changing fontface, size, etc.,) and after placing, SketchUp immediately updates the registry attributes of these keys.

So, @gkernan Garry, you can use the registry read paradigm for Windows.
(Pay heed to the correction I added to post 5 above.)

I don’t know if it works similar on the Mac. Perhaps John can run a test.
I also wonder if Ruby PStore lib can read OSX plist files?
http://ruby-doc.org/stdlib-2.2.4/libdoc/pstore/rdoc/PStore.html


#9

I haven’t used that particular lib, but in reading its page I see nothing that suggests it can access a plist. A plist is an xml file using a particular schema specified by Apple. The PStore page doesn’t mention xml or a specific schema, though it does mention marshal, a separate and different mechanism.


#10

To backtrack a little…
I do not think that reading these settings is advisable - even if you could do it effectively.
Just have your tool offer a settings dialog for the 3dText, which takes the users input for font, height etc.
You might also want to fix some values anyway ?
When the user OKs the dialog, then you use

Sketchup.write_default('GKs_LovelyTool_3dText', 'font', @font_name)

etc to save values externally.
When you tool is initially run, you use

Sketchup.read_defaults('GKs_LovelyTool_3dText', 'font', nil)

to get the values.

If it returns nil [e.g. first use] then open the settings dialog to get/save the defaults…
I suggest that you offer the settings dialog as a submenu option to your tool’s menu item.

The above method sets up global defaults for your tool.
However, if the user is likely to prefer different settings on a model by model basis, then instead of using write_defaults() etc, why not consider adding the values to your own attribute dictionary attached directly to each model, using

model.set_attribute('GKs_LovelyTool_3dText', 'font', @font_name)

and

model.get_attribute('GKs_LovelyTool_3dText', 'font', nil)

in a similar way ?


#11

Thanks Steve, I’ll need to remember this. (For some reason I was also thinking maybe Mac plist were JSON based.)

Oh well then that’s good info as well, as there are a number of gems and libs that can read XML.
I’ve pulled info out of XML (SKM files) with plain ol’ String#scan.


#12

Lots of good ideas - but I think I’ll stay with text files. Much easier for me to help users I can grab user setup very simply.

I just set up a simple struct that I read at startup and continue to use. In my case I save it back to disk anytime there is a change. This stategy is totally backwards compatible and shouldn’t be affected for years to come.

CONFIG = Struct.new(:left, :top, :width, :height, :font_height, :font_name)

def save_structs(root, obj, text_file)
  filename = File.join(root, "config", text_file)
  File.open(filename, 'w') { |file|
    obj.each_pair{ |key, val|
      file.puts "#{key}=#{val}"
    }
  }

end

def read_configs(root)
filename = File.join(root, “config”, “config.txt”)

  # initialize all elements
  @@cfgs.left = 0
  @@cfgs.top = 0
  @@cfgs.width = 0
  @@cfgs.height = 0
  @@cfgs.extra_width = 0
  @@cfgs.font_height = 230.mm
  @@cfgs.font_name = 'Arial'
  if (File.exist?(filename))
    begin
      File.open(filename, 'r') { |file|
        file.each_line("\n") do |row|
          txt = row.strip.split('=')

          case txt[0]
            when 'left';        @@cfgs.left = txt[1].to_i
            when 'top';         @@cfgs.top = txt[1].to_i
            when 'width';       @@cfgs.width = txt[1].to_i
            when 'height';      @@cfgs.height = txt[1].to_i
            when 'font_height'; @@cfgs.font_height = txt[1].to_f.mm
            when 'font_name';   @@cfgs.font_name = txt[1]
          end
        end
      }
    rescue StandardError => e
      UI.messagebox(e)
    end
  end
end