I have tried to utilize ChatGPT to help me in the creation of a plugin for SketchUp but unfortunately the AI can’t get the plugin to work no matter how much information I give it. My last resort would be to potentially hire someone who could create a small plugin for me. I have some experience in programming languages but it’s not enough to flesh out the extension. If anyone could help me, please let me know. People tell me to be careful to not be scammed, so I would prefer if it was someone from this community who knows/remembers me and whom I know but it’s not a must. So if you don’t mind an hour or two of your time and would like to earn a little, feel free to DM.
The plugin in mind should simply batch rename selected/highlighted scenes in SketchUp and add a numerical suffix at the end. It should have a dialog box callout with a text field to input the new name and 2 buttons. It’s relatively primitive. I’d also like a separate toolbar for it or alternatively an ability to assign a shortcut to the plugin. No need for an icon, as I can design one myself and replace the default one later. ChatGPT nearly managed to help me but it failed in the end because it renames every single scene regardless of what’s been highlighted.
It seems it have a similar function you want. (The video will start from 2:58 to show the function)
.
BTW:
I don’t think there is a way in Sketchup Rubi API to check what is selected/highlighted in menus/Trays of SketchUp UI. You need to write your own interface to select scenes… (as above)
And S4U’s plugin did not show up in my search results (apparently it’s not easy to find it through simple google searches), which is the reason I resorted to AI.
Regarding your stance about AI, while I don’t defend or condone its existence, because I find AI generated art that’s being promoted and pushed, to be a sort of an “insult” to real artists and true art forms, I am of the opinion that those industries/companies who don’t implement or at least get familiar with AI, will not do well in the coming future. The industry is changing and AI is not at all “super overhyped”. It cannot do everything, it will never replace humans but there’s more to AI than generating images. We use AI in our company to our advantage. AI already assisted me in creating an HTML animation, which was very well accepted. Not being hostile towards AI and trying to use it to your advantage might be a more open minded approach in my opinion.
So this first one I made 2 days ago with the (paid) 3.5 version of ChatGPT. This was intended to be used without a dialog box, with the means of the Ruby API window:
def batch_rename_highlighted_scenes(new_name_prefix)
model = Sketchup.active_model
model.start_operation("Batch Rename Highlighted Scenes", true)
# Get all scenes in the model
scenes = model.pages
# Loop through all scenes and rename highlighted ones
scenes.each_with_index do |scene, index|
if scene != model.pages.selected_page && scene.use_camera?
new_name = "#{new_name_prefix} #{index + 1}"
scene.name = new_name
end
end
model.commit_operation
end
# Example usage: batch_rename_highlighted_scenes("Scene")
ChatGPT also provided me with a command line:
batch_rename_highlighted_scenes("YourPrefix")
However, this did not work because instead of renaming only highlighted scenes, it renamed every Scene I had. After some time of back and forth with the AI, I decided to leave it and try the next day again.
Second time I used the free version of ChatGPT and tried to make the plugin with a toolbar icon and a dialog callbox.
module BatchRenameScenes
def self.rename_scenes(base_name)
model = Sketchup.active_model
selected_scenes = model.pages.selected
return unless selected_scenes.any?
active_scene_index = model.pages.active_page.index if model.pages.active_page
selected_scenes.each_with_index do |scene, index|
new_scene_name = "#{base_name} #{index + 1}"
scene.name = new_scene_name
end
model.pages[active_scene_index].make_current if active_scene_index
end
def self.show_dialog
dialog = UI::HtmlDialog.new(
{
title: "Batch Rename Scenes",
style: UI::HtmlDialog::STYLE_DIALOG
}
)
# Set the HTML content for the dialog
dialog.set_html(<<-HTML)
<html>
<head>
<title>Batch Rename Scenes</title>
<style>
body {
font-family: sans-serif;
}
</style>
</head>
<body>
<div style="padding: 20px; text-align: center;">
<label for="newName">Base Name:</label>
<br>
<input type="text" id="newName" style="width: 80%;">
<br><br>
<button onclick="renameScenes()">Rename</button>
<button onclick="closeDialog()">Cancel</button>
</div>
<script>
function renameScenes() {
var baseName = document.getElementById('newName').value;
sketchupAPI.renameScenes(baseName);
sketchupAPI.closeDialog();
}
function closeDialog() {
sketchupAPI.closeDialog();
}
</script>
</body>
</html>
HTML
# Set the position of the dialog to the center of the screen
dialog.center
dialog.add_action_callback("renameScenes") do |dlg, base_name|
rename_scenes(base_name)
end
dialog.add_action_callback("closeDialog") do |dlg, _params|
dlg.close
end
dialog.show
end
end
toolbar = UI::Toolbar.new("Batch Rename Scenes")
cmd = UI::Command.new("Batch Rename Scenes") { BatchRenameScenes.show_dialog }
cmd.small_icon = "BatchRenameScenes.png" # You can replace "BatchRenameScenes.png" with your own square icon file
cmd.large_icon = cmd.small_icon
cmd.tooltip = "Batch Rename Scenes"
toolbar = toolbar.add_item(cmd)
toolbar.show
UI.menu("Extensions").add_item("Batch Rename Scenes") { BatchRenameScenes.show_dialog }
This was 50% successful, except clicking on “Rename” did not do anything at all. ChatGPT edited the script several times, trying to get it to work but sadly unsuccessfully. I was too tired at this point, so I just closed everything.
I didn’t mean to offend you with my comment. Sorry, using a smiley ( ) , I thought you understood my “humour”…
Anyway, - without further discussing AI - here it’s half-baked code, more or less working, but nowhere near finished and ugly. Use it or leave it… as you like! Copy-paste it to Ruby Console to try.
. .
Because the topic opener said he can do it… anyway - is is a just snippet - you need to create a proper Extension structure… and include the icon in the extension folder, beside this .rb file.
I will think about “a,b,c” later… (intentionally no deadline given )
I also experimented with using ChatGPT to quickly craft some code for renaming scenes. The outcome was quite intriguing! While a few tweaks were necessary, about 90% of the code was effectively written by AI. It’s fascinating to see how these tools can aid in our coding endeavors.
module CURIC
module SceneManager
module Rename
class << self
attr_accessor :dialog # Allows setting and getting of the @dialog instance variable
# Entry point to run the plugin
def run
unless Object.const_defined?('CURIC::SceneManager::Selection')
return UI.messagebox("Please install Curic Scene Manager to use this plugin")
end
@dialog && @dialog.visible? ? @dialog.bring_to_front : show_dialog
end
# Displays a dialog box for renaming scenes
def show_dialog
setup_dialog
@dialog.set_html(html_content)
@dialog.show
end
# Defines HTML content for the dialog
def html_content
<<-HTML
<!DOCTYPE html>
<html>
<head>
<link href="https://cdn.jsdelivr.net/npm/tailwindcss@2.2.19/dist/tailwind.min.css" rel="stylesheet">
</head>
<body class="bg-gradient-to-r from-black to-red-900 p-6">
<div id="app" class="max-w-sm mx-auto bg-gray-700 text-white shadow-md rounded px-8 pt-6 pb-8 mb-4">
<h1 class="text-lg mb-4">Scene Manager</h1>
<div class="mb-4">
<label class="block text-gray-700 text-sm font-bold mb-2" for="type-select">
Type:
</label>
<select id="type-select" v-model="options.type" class="shadow border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline">
<option value="Replace Text">Replace Text</option>
<option value="Add Text">Add Text</option>
</select>
</div>
<div class="mb-4" v-if="options.type === 'Replace Text'">
<label class="block text-gray-700 text-sm font-bold mb-2">
Find:
<input type="text" v-model="options.find" placeholder="Find" class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 mb-3 leading-tight focus:outline-none focus:shadow-outline">
</label>
<label class="block text-gray-700 text-sm font-bold mb-2">
Replace:
<input type="text" v-model="options.replace" placeholder="Replace" class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 mb-3 leading-tight focus:outline-none focus:shadow-outline">
</label>
</div>
<div class="mb-4" v-else>
<label class="block text-gray-700 text-sm font-bold mb-2">
Add Text:
<input type="text" v-model="options.add_text" placeholder="Add Text" class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 mb-3 leading-tight focus:outline-none focus:shadow-outline">
</label>
<label class="block text-gray-700 text-sm font-bold mb-2" for="position-select">
Add Position:
<select id="position-select" v-model="options.add_position" class="shadow border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline">
<option value="prefix">Prefix</option>
<option value="suffix">Suffix</option>
</select>
</label>
</div>
<div class="flex items-center justify-between">
<button @click="applyOptions" class="bg-red-600 hover:bg-red-800 font-bold py-2 px-4 rounded focus:outline-none focus:shadow-outline">
Apply
</button>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.7.14/dist/vue.js"></script>
<script type="text/javascript">
new Vue({
el: '#app',
data: function() {
return {
options: {
type: 'Replace Text',
find: '',
replace: '',
add_text: '',
add_position: 'prefix',
}
}
},
methods: {
applyOptions() {
sketchup.apply(this.options);
}
}
})
</script>
</body>
</html>
HTML
end
# Sets up the dialog with specified properties
def setup_dialog
@dialog = UI::HtmlDialog.new(dialog_title: "Rename Scenes", max_width: 500, max_height: 500)
@dialog.center
@dialog.add_action_callback("apply") { |_a, options| apply(options) }
end
# Applies renaming logic based on user input
def apply(options)
pages = CURIC::SceneManager.selection.get_sketchup_item
return UI.messagebox("Please select pages to rename") if pages.empty?
if options['type'] == 'Replace Text'
return UI.messagebox("Please input find text") if options['find'].empty?
elsif options['add_text'].empty?
return UI.messagebox("Please input add text")
end
rename_pages(pages, options)
UI.messagebox("Rename success: #{pages.size} Scene(s)")
CURIC::SceneManager.refresh
end
# Validates input and performs renaming
def rename_pages(pages, options)
model = Sketchup.active_model
model.start_operation("Rename Scenes", true)
pages.each do |page|
page.name = rename_page(page, options)
end
model.commit_operation
end
# Determines the new name for a page
def rename_page(page, options)
case options['type']
when 'Replace Text'
replace_text_in_name(page.name, options)
else
add_text_to_name(page.name, options)
end
end
# Replaces text in the scene name
def replace_text_in_name(name, options)
name.gsub(options['find'], options['replace'])
end
# Adds text to the scene name
def add_text_to_name(name, options)
options['add_position'] == 'prefix' ? "#{options['add_text']}#{name}" : "#{name}#{options['add_text']}"
end
end
# Initializes the plugin
unless file_loaded?(__FILE__)
ex = SketchupExtension.new('Rename Scenes', __FILE__)
ex.creator = 'Vo Quoc Hai & GPT'
Sketchup.register_extension(ex, true)
cmd = UI::Command.new('Rename Scenes') { CURIC::SceneManager::Rename.run }
UI.menu('Plugins').add_item(cmd)
end
end
end
end
file_loaded(__FILE__)
Hey Dezmo, thank you for clarifying. I also apologize, it’s not easy to discern humour from sarcasm in a text, hence my reply. Thank you also for the script. I don’t exactly know what you mean by “ugly”, because I have no professional knowledge of programming languages so it all looks the same to me But I appreciate you taking time. I like the beer icon btw!
Hey Curic! Didn’t know you were also active in this Forum. Let me use this and say hats off to you for your plugins. They are an essential part of my workflow and I use several of them on a daily basis.
I see you were successful with ChatGPT! I wasn’t that luck with my attempt, haha! But yes, it’s truly fascinating what it can do!
Thank you so much for your kind words! I’m glad to hear that my plugins are a part of your daily workflow. As for ChatGPT, I’m just exploring its possibilities too. Wishing you continued success and enjoyment in your projects!
@VahePaulman I went ahead and created a registration file and a loader file using your code in “main.rb”. The gist of your extension looks like this (with the exception of the added Dezmo icon):
I believe that Dezmo may be correct that selecting active scenes (as in the Scenes in the Scenes panel/tray) will not work. I don’t use Mac so I’m guessing the Scene Manager in Curic’s video is also an extension and not the Mac version of the Scenes panel/tray.
Anyway, you can see that they are getting the scenes in the model, displaying them, and selecting from them. That may have been a point where you went off course a bit.
You have some working examples now. But I’m going to see if I can fix your version as well. “Practice makes perfect” they say (and let’s hope ‘they’ are right).
Here is your version with the adjustments for making an extension out of it:
If I’m honest I didn’t understand half of what you wrote because I’m not familiar what is a loader and what is a registration file? The s4u plugin suggested by Dezmo seems to have done the job but now as I have the seen what making a plugin looks like I’m intrigued of trying it again. This time asking SketchUp to highlight all scenes that contain a certain number.
ChatGPT tells me:
In SketchUp, the model.pages.selected expression refers to a collection of the currently selected scenes (or pages) within the active SketchUp model"
Also that
model.pages.selected and the currently active scene are not the same.
model.pages.selected: This represents a collection of scenes (or pages) that are currently highlighted or selected in the SketchUp interface. These are scenes that the user has interacted with, typically by clicking on them or using a selection method. You can perform operations on the scenes in this collection.
Currently Active Scene: The currently active scene, on the other hand, is the scene that is currently set as the “active” scene in the SketchUp model. The active scene is the one that will be displayed when you switch to that scene. You can access the active scene using model.pages.active_page.
Dezmo said there is no way in SketchUp to check what is selected/highlighted. But then I don’t understand what is the “model.pages.selected” intended for.
There is no such a #selected method in Class: Sketchup::Pages (and at all in Sketchup Ruby API)
Again WRONG! Actually it is:
The Pages #selected_page method is used to retrieve the currently selected page.
Still saying.
It is representing the user interface selection - It is poorly worded and the syntax suggests ruby code, which is very misleading, as I told you can not retrieve it by Ruby API.
Woah, thank you! I was aware that ChatGPT makes mistakes or rather spreads misinformation (tested it personally on historically proven questions and got lies as a reply). But I didn’t expect that it would straight out lie to such degree. I’ll make sure to let it know tomorrow, haha!
So, for SU extensions, there is a registration file and an extension folder in the SU Plugins folder (something like, C:\Users\username\AppData\Roaming\SketchUp\SketchUp 2022\SketchUp\Plugins\BatchRenameScenes). This registration file has the same name as the extension folder. For example, you might see the “su_sandbox.rb” registration file in the SketchUp Plugins folder along with the “su_sandbox” folder if you have the Sandbox Tools extension installed. For a basic setup, the registration file in the Plugins folder points at the ‘main.rb’ in the extension folder. The registration file I shared points at a loader file instead of a ‘main’. This is just an additional step where the loader file points at the main.rb and some file paths are set up. This can be helpful for organization. For example you could have:
That’s more than you need to get started but it’s worth mentioning.
I’m not sure that is possible either… at least as far as highlighting scenes in the Scenes Panel. This is similar to the issue of using ‘selected scenes’. You can’t necessarily use selected scenes-that-are-in-the-SU-Scenes-panel. You need your extension to display the scenes in some way, then select them there. Same for highlighting. You could display the scenes in your extension, search the scenes for a number and highlight those (Or search the scenes and only display those with a certain number, etc.). But highlighting in the Scenes panel… I doubt that. But I haven’t monkeyed around with scenes much to know what’s possible…
I have a basic scene re-namer working. It stared using your example… but now it’s its own animal.
Ut-oh. ;^)! I just meant to imply that you bust out code like it aint no thang. But you took it upon yourself to demonstrate the truth of the matter :). I’ll take a look at those links.