SketchUp整蠱大賞
SketchUp 中的 ruby 控制臺作為自動化操作的利器,同時也可以是“整活”的窗口。本篇介紹幾個簡單的整蠱代碼。不過需要注意,這些“整蠱代碼”的主要寫作目的在于其表演性和娛樂性,而不應(yīng)該關(guān)注其破壞性,更不能加以惡意。
這些代碼同時也可以對“正統(tǒng)”的 SU Ruby 使用提供一定的思路借鑒,尤其是可以避免在編寫代碼過程中出紕漏而無意中整蠱了自己。
*這是“SketchUp不務(wù)正業(yè)系列”中的一篇,文中淺紫色文字為“不務(wù)正業(yè)”對“正業(yè)”的借鑒參考。
| 【本期目錄】 | |
一、死循環(huán) 二、背景閃爍 三、莫名的響聲 四、組件鎖死 五、要命的保存 | 其中第1個為簡陋且破壞性強的代碼,不推薦使用;第2、3個通過線程實現(xiàn)功能;第4、5個則通過 SU Ruby 自帶的監(jiān)控類實現(xiàn)。 |
一、死循環(huán)
這是一個最簡單最簡陋也相當(dāng)危險的代碼:
while true do end在控制臺中輸入以上代碼會使得控制臺主進程進入死循環(huán):

此時控制臺置頂,SketchUp 界面不能進行其他操作,整個程序處在未響應(yīng)的狀態(tài)。此時只能強制關(guān)閉程序,只要 SU 打開了模型文件,無論保存與否,這都是一個很不合適的玩笑。
類似的做法還有長時間的等待:
sleep 10000以上代碼使主進程等待10000秒,其效果也近乎等于死循環(huán)了。
正業(yè) 但是反過來說,如果自己編寫的代碼在考慮不周時,有可能出現(xiàn)死循環(huán)的狀態(tài);又或者有繁復(fù)的計算過程,在有些情況下需要大量等待時間。這些情況下如果不加以預(yù)處理,很有可能表現(xiàn)出來就是這樣的一個整蠱效果,因此需要特別注意。
二、背景閃爍
以下是一個稍微復(fù)雜的整蠱代碼:
def changeBkColor()mod=Sketchup.active_modelmod.rendering_options["BackgroundColor"]=(rand()*0xffffff).roundendth_1=Thread.new{while true dochangeBkColor()sleep(0.5)end}
執(zhí)行以上代碼會使得背景顏色以 2Hz 的頻率隨機變換顏色:

以上代碼中第1-4行定義了一個使當(dāng)前模型背景顏色隨機變換一次的方法(函數(shù)),每次調(diào)用 changeBkColor 時就會根據(jù)隨機函數(shù)重新設(shè)置一次背景顏色。而第6-10行新建了一個線程,規(guī)定了一個死循環(huán),循環(huán)內(nèi)每調(diào)用一次剛定義的方法(函數(shù))就在線程內(nèi)等待0.5秒,并將此線程命名為 th_1,以便在主線程中保持對它的控制。
這里同樣是使用了死循環(huán),但是由于新建了一個線程,并不會占用控制臺的主進程,因此即使線程內(nèi)是死循環(huán),也不會造成程序卡死。這番操作之后如果關(guān)閉 ruby 控制臺,等到被整蠱者回到屏幕前將會無所適從(當(dāng)然這里假設(shè)他沒有了解過 ruby 控制臺的具體功能)。
這個方法和粗暴的主線程死循環(huán)比起來,顯然要溫和很多。不僅僅因為其不會造成卡死,更因為它可以重新打開控制臺后取消這個循環(huán):
th_1.kill 正業(yè) 這是使用線程的優(yōu)勢之一,可以從外部停止失控的線程。對應(yīng)到正統(tǒng)的 SU Ruby 使用場景中,如果遇到計算過程繁雜、誤操作可能造成運行時間過長的情況,可以新建線程單獨管理,如果較長時間未響應(yīng)則可以人工中止過程而不至于卡死。
另外也可以使用 UI 模塊中的 .start_timer 和 .stop_timer 方法來實現(xiàn)不占用主線程的死循環(huán),這里不額外舉例了。
三、莫名的響聲
以下代碼具有隱藏性和硬件局限性:
th_2=Thread.new{while true doUI.beep if rand()>0.5sleep 10end}
代碼中創(chuàng)建了一個名為 th_2 的線程,使其每10秒就有二分之一的概率發(fā)出系統(tǒng)提示音。停止它的方法和上一個方法“背景閃爍”一樣:
th_2.kill以上代碼中的 .beep 方法調(diào)用系統(tǒng)提示音,一般與彈窗一并出現(xiàn),作為對用戶的提醒。如果像以上代碼中濫用,就會對用戶造成很大的疑惑和困擾。不過,本方法被“靜音玩家”所免疫。
四、組件鎖死
以下代碼造成的效果很具有迷惑性:
class NotIntoInstance < Sketchup::ModelObserverdef onActivePathChanged(model)model.close_active unless model.active_path.nil?endendmod_obs_1=NotIntoInstance.newSketchup.active_model.add_observer(mod_obs_1)
此方法定義了一個監(jiān)控類,對當(dāng)前模型的狀態(tài)進行監(jiān)控,當(dāng)檢測到模型打開了組編輯器,就會立刻關(guān)閉當(dāng)前組件。所以運行以上代碼后,無論是雙擊組件還是右鍵菜單中選擇“編輯組”,表現(xiàn)上都是無法進入組編輯器:

當(dāng)然,這個方法一樣是可逆的,前提是新加入的監(jiān)控類實例在控制臺中留有引用(以上代碼之中的 mod_obs_1 即實例的引用):
Sketchup.active_model.remove_observer(mod_obs_1)五、要命的保存
以下是一個娛樂性很強的整蠱代碼:
class AreYouARobot < Sketchup::ModelObserverdef onPreSaveModel(model)while true doa=rand(99)b=rand(99)c=a+bres=UI.inputbox(["#{a}+#="])redo unless res.respond_to?(:[])break if res[0] == c.to_sendendendmod_obs_2=AreYouARobot.newSketchup.active_model.add_observer(mod_obs_2)
運行完代碼之后,每一次保存都需要進行一次“100以內(nèi)加法”的驗證碼測試,如果輸入錯誤則會重新跳出驗證碼,如果不正確輸入計算結(jié)果,就會造成實際上的死循環(huán):

此功能同樣通過監(jiān)控類實現(xiàn),因此復(fù)原功能也是通過移除監(jiān)控:
Sketchup.active_model.remove_observer(mod_obs_2)以上五個整蠱代碼除了第一種“死循環(huán)”具有很強的破壞性,另外四個方法有相應(yīng)的功能復(fù)原手段。具體來說:第2、3個是通過多線程實現(xiàn)的后臺運行,因此功能復(fù)原使用的是中止進程;而第4、5個則是通過 SU Ruby 中自帶的監(jiān)控類實現(xiàn),因此對應(yīng)的復(fù)原是使用移除監(jiān)控的方法。
正業(yè) 這兩類方法也是比較好的后臺運行思路,既可以暗自地起到“整蠱”的作用,也可以實時地檢測自定義工具、自定義功能的觸發(fā)條件。正如本系列創(chuàng)作的初衷,雖然名為“不務(wù)正業(yè)”,但怪異旁門的方法也能夠給“正統(tǒng)”的使用方式以參考借鑒。
(都看到這了,點個贊唄)
本篇文章是“SketchUp不務(wù)正業(yè)系列”的其中一篇,編號為SU-2021-S01,更多與SketchUp Ruby有關(guān)的其他文章可以點擊公眾號菜單中的“SU Ruby”選項獲得文章的目錄。
