Deluxe Paint w praktyce (odc. 42.) ---------------------------------- MACRO W DELUXE PAINT CZYLI KREW POT I ÎZY Deluxe Paint V ma wreszcie moûliwoôê korzystania z makrodefinicji ARexxa. Jednak kiedy zaczâîem zajmowaê sië tym zagadnieniem, postanowiîem nadaê wîaônie taki tytuî odcinkowi o ARexxie w Deluxe Paint. Stanisîaw Wësîawski Zacznë wyjâtkowo od wybrzydzania. Co prawda w odcinku, w którym po raz pierwszy wspomniaîem o makrodefinicjach Deluxa, byîem peîen zachwytu. Teraz jestem, powiedzmy, tylko zadowolony. Ale dlaczego, u licha, nie moûna w rozkazach Deluxowego ARexxa znaleúê ani jednej instrukcji rozpoznajâcej kolor piksela na którym stoi kursor? Gdyby ta drobna instrukcja istniaîa, tworzenie filtrów podobnych do tych z PersonalPainta, byîoby drobiazgiem. Zaczâîem wiëc eksperymentowaê z ARexxem Deluxe Painta takim, jaki jest. Makrodefinicje w Deluxe Paint tworzy sië w niemal identyczny sposób jak w CED-zie. Jest to (CED) jeden z dwóch chyba najlepszych programów stworzonych dla Amigi, drugi to Opus 4.x ("piâtki" nie lubië). Naciskamy wiëc klawisze [Prawa Amiga][M], wykonujemy pewne czynnoôci programem i naciskamy ponownie [Prawa Amiga][M]. Makrodefinicja zostaîa zapamiëtana. W odróûnieniu jednak od CED-a Deluxe Paint pozwala jâ "zobaczyê" (jest w RAM:T) i edytowaê dowolnym edytorem tekstu. Poza tym powstaje automatycznie lub moûe zostaê przez nas napisana w ARexxie. W CED-zie po pierwszej sekwencji klawiszy trzeba podaê klawisz, który w przyszîoôci uruchomi "nagrywane" wîaônie makro, w DP klawisz (jeden z funkcyjnych [F1]...[F0]) podaje sië na koïcu. Reszta identycznie. Spëdziîem wiele godzin nad tâ zabawâ i ûeby skoïczyê z uûalaniem sië nad sobâ, podam od razu, z czym sâ najwiëksze problemy. Naleûy bezwzglëdnie sprawdzaê skrypt makrodefinicji w wersji "pod CED-a". Rozkazy rysowania zastëpujemy poleceniem "TEXT n" i poprzedzamy (tylko raz na poczâtku skryptu) rozkazem MENU 0 3. Program wypisze na osobnym oknie CED-a obliczone wartoôci. Dlaczego takie komplikacje? Otóû w wypadku np. postawienia dwukropka zamiast ôrednika CED wywiesza odpowiedni komunikat ARexxa typu "bîâd taki to a taki w linii nr". Sprawdzamy linië, poprawiamy bîâd i jesteômy w domu. W Deluxe Paint, program pokazuje w takim wypadku GURU albo bez sîowa zawiesza sië i pozostaje nam tylko reset systemu. Osoby bardziej wtajemniczone w ARexx niû ja pewnie potrafiâ jakoô sobie z tym poradziê, ja jednak znam tylko tyle ARexxa, ile muszë. Pomimo zastosowania tych mâdrych uwag oglâdaîem GURU wiele razy przy poprawnie napisanych skryptach. Wielodniowe ôledztwo skierowaîo podejrzenia na skâdinâd ôwietny program MCP, CED, ARexx oraz sam Deluxe. Zrobië tu kilka maîych dygresji. Otóû przy pracy z DP5 i animacjami zauwaûyîem gwaîtowne drûenie obrazu monitora. W porë nagrana animacja (póki jeszcze litery w menu i requesterach byîy widoczne) i reset ratowaîy pracë. W tym wypadku najbardziej prawdopodobnym winowajcâ byî wygaszacz ekranu z MCP, który usiîowaî sië wîâczyê. Úle to ôwiadczy nie tyle o MCP, ile o DP5. Pytaî mnie teû kiedyô Czytelnik z Opola o problem z A600, monitorem od PC i Deluxem4. Nie potrafiîem na to pytanie sensownie odpowiedzieê. Swojâ drogâ, namawiaîbym Czynniki Decyzyjne w Redakcji o zbieranie takich informacji i próby odpowiedzi na nie na îamach Magazynu. Amiga powoli, ale jednak obrasta w software oraz hardware i konflikty w tym gronie sâ czësto trudne do wyjaônienia. Wracajâc do ôledztwa, to na liôcie podejrzanych ostaî sië CED z uruchomionym ARexxem. Sprawa byîa poszlakowa, ale sprawdzonym sposobem na unikniëcie kîopotów jest reset komputera po napisaniu, sprawdzeniu i zapisaniu skryptu. Pierwszy skrypt, który postanowiîem napisaê, byî programem do rysowania sinusoidy na ekranie Deluxe Painta. Dlaczego? Wydawaîo mi sië, ûe jak to sië uda zrobiê, to reszta bëdzie juû drobnostkâ. Algorytm rysowania sinusoidy znalazîem w ksiâûce*, reszta jest moja. A wiëc na poczâtek piszemy: /* */ ADDRESS "DPAINT.1" CALL ADDLIB 'rexxmathlib.library',0,-30 LOCKGUI;PANEL OFF;TITLE OFF Pierwsze dwie linie sâ oczywiste, trzecia odwoîuje sië do koniecznej w tym wypadku biblioteki matematycznej -- bëdzie uûywana funkcja SIN(). Ostatnia linia to juû typowe dla Deluxowego ARexxa komendy powodujâce odsîoniëcie i przygotowanie ekranu do pracy. Ôredniki pozwalajâ w kaûdym ARexxie poîâczyê kilka rozkazów w jednej linii (odwrotnie dziaîa przecinek). YM=500;M=YM/2 /* maksymalna wartoôê w pionie */ H=100;W=0.4*0.0314159;D=0 /* H=amplituda, W=czëstotliwoôê, D=przesuniëcie */ XL=0;XR=500;Ye1=H*SIN(W*XL+D) /* XL=minimum, XR=maksimum */ IF Ye1>=0 THEN Ye1=M-Ye1;IF Ye1<0 THEN Ye2=M+ABS(Ye1) Xe1=XL Kolejne linie warto uzupeîniê o komentarz dotyczâcy zmiennej H -- powinna byê równa lub mniejsza zmiennej M. Czëstotliwoôê (W) jest dobrana przeze mnie eksperymentalnie, a Ye1 zawiera wîaôciwâ definicjë sinusoidy. Nazwy zmiennych teû majâ pewien haczyk. Otóû rozkazy makr DP zawierajâ opcje nazywane czasami X, X1 itd. Na przykîad rozkaz MOVETO 50 50, polecajâcy przesunâê kursor do pozycji okreôlonej podanymi wspóîrzëdnymi, moûna napisaê równieû jako MOVETO X 50 Y 50. Lepiej dla wîasnego dobra unikaê tworzenia zmiennych o takich wîaônie nazwach. MOVETO XL M;MBUTTONS SELECTUP /* lewy klawisz myszy zwolniony */ DO Xe2=XL TO XR;Ye2=H*SIN(W*Xe2+D) IF Ye2>=0 THEN Ye2=M-Ye2;IF Ye2<0 THEN Ye2=M+ABS(Ye2) Powyûsze linie naleûâ do algorytmu, ale dalej jest juû coô mojego... N=Xe1;CALL KONWERSJA;Xe1=N;N=Ye1;CALL KONWERSJA;Ye1=N N=Xe2;CALL KONWERSJA;Xe2=N;N=Ye2;CALL KONWERSJA;Ye2=N Trochë rysowania ... MOVETO Xe1 Ye1;MBUTTONS SELECTDOWN /* przesuï kursor, naciônij lewy klawisz */ MOVETO Xe2 Ye2;MBUTTONS SELECTUP /* przesuï kursor, zwolnij klawisz */ Xe1=Xe2;Ye1=Ye2;END /* koniec pëtli */ UNLOCKGUI;PANEL ON;EXIT /* przywróê normalny ekran, zakoïcz program */ Teraz pora na wyjaônienie "mojego". Parë îadnych GURU minëîo, nim zorientowaîem sië, ûe ARexx Deluxa przyjmuje tylko i wyîâcznie caîkowite liczby dodatnie. Przynajmniej w rozkazach dotyczâcych malowania na ekranie. Potëûny ARexx.guide (dostëpny w Aminecie) proponowaî w tym wypadku jakieô dziwne rozwiâzanie. Po pewnym czasie ulepiîem swoje: KONWERSJA: IF VERIFY(N, '.', 'm')=0 THEN RETURN /* jeûeli N=0 to moûe tak pozostaê */ N=(LEFT(N,VERIFY(n, '.', 'm')-1));RETURN /* jeûeli ma dziesiëtne to wyrzuê je razem z kropkâ */ Podprogram Konwersja nie bierze w tym wypadku pod uwagë liczb ujemnych, zajmuje sië tylko liczbami zmiennoprzecinkowymi. Litera "m" nie ma w tym miejscu nic wspólnego ze zmiennâ "M" programu. Jest to tylko opcja rozkazu ARexxa, który liczy miejsce wystâpienia kropki dziesiëtnej i wyrzuca jâ razem z resztâ liczby, która jak na ARexx przystaîo jest "stringiem". No i co z tego? Wiele programów rysuje sinusoidë i to o wiele szybciej. Jednak jest to furtka, przez którâ moûna wejôê do skryptów rysujâcych najróûniejsze funkcje matematyczne. Zostawiam to osobom bardziej zaprzyjaúnionym z matematykâ i programowaniem. Mój skrypt dziaîa pod warunkiem, ûe uruchomimy go na ekranie 640 x 512, uaktywnimy w TOOLBOX jakieô narzëdzie do rysowania "od rëki" i damy mu jakiô brush. Moûe to byê brush systemowy lub cokolwiek, co przyczepimy do kursora. Sam skrypt moûemy ostroûnie rozbudowaê, np. zmieniajâc w pëtli niektóre parametry sinusoidy. Ale proszë pamiëtaê o ostrzeûeniach na poczâtku tekstu. Pierwsza ilustracja pokazuje kilka rysunków sinusoidy stworzonych opisanym wyûej makrem. Zmieniajâc wartoôci "W" i "H" moûna narysowaê róûne wykresy. Na drugiej ilustracji mamy sinusoidë rysowanâ nie okrâgîâ plamkâ, ale îukowatym brushem wyciëtym z pocieniowanej kuli. Druga sinusoida -- "druciana" -- narysowana zostaîa cienkim îukiem, skryptem sinusoidy z maîâ modyfikacjâ -- do instrukcji pëtli dodano polecenie rysowania w osi X co piâtego punktu -- "DO ... BY 5". Myôlâc intensywnie nad stworzeniem jakiegoô przydatnego skryptu, przypomniaîem sobie odcinki dotyczâce tworzenia tekstur. Skrypt taki nie musi juû korzystaê z biblioteki matematycznej, ale za to uûyje funkcji losowej. Pierwsze linie skryptu pomijam i przechodzë do sedna sprawy: DO I=1 TO 10 /* wykonaj dziesiëê razy */ SETFGCOLOR 1 /* rysuj kolorem nr 1 z palety */ N=I/2;CALL KONWERSJA /* zmieï liczbë na caîkowitâ */ IF N*2=I THEN SETFGCOLOR 0 /* jeûeli N parzyste rysuj kolorem tîa */ XE=100;YE=300;DO NY=100 TO 300 /* rysuj od Y=100 do Y=300 */ CALL LOS;MOVETO R NY /* wylosuj liczbë, postaw jâ na osi X */ MBUTTONS SELECTDOWN;MBUTTONS SELECTUP /* naciônij i zwolnij klawisz */ END;END;SETFGCOLOR 1;UNLOCKGUI;PANEL ON;EXIT /* zakoïczenia pëtli i programu */ Skrypt pokrywa kwadratowy obszar losowo ustawianym brushem. Nastëpnie powtarza te czynnoôci kolorem tîa, co spowoduje wymazanie niektórych miejsc. Rysowanie i mazanie wykonuje w sumie dziesiëê razy. Podprogram Konwersja jest taki sam jak poprzednio, najwaûniejszy jest jednak podprogram losowania: LOS: R=RANDOM(XE, YE, TIME(S));RETURN ARexx losuje wyjâtkowo podle. Funkcja Random dziaîa tylko na liczbach caîkowitych od XE do YE. Ale w takim wypadku przypadkowoôê jest wîaôciwie ûadna. Niezbëdnym ziarnem generatora jest tu funkcja TIME(s), która pobiera czas z Systemu, w tym wypadku w sekundach (s). I tak zobaczymy na ekranie "gëstsze" upakowanie brushy w ôrodku zakresu niû na jego koïcach, ale zawsze lepsze to niû nic. Skrypt produkuje surowiec do "tekstury". Rozmiar pola dziaîania moûna oczywiôcie dowolnie zmieniê. Jeûeli jednak chcemy pójôê krok dalej, moûemy przed "UNLOCKGUI" dodaê parë nowych linii: BRUSH 100 100 200 200 CUT /* wycinanie namalowanego obrazka */ OUTLINEBRUSH;TRIMBRUSH /* "obwódka i strzyûenie" */ CLEAR;MOVETO 150 150 /* wyczyôê ekran i postaw kursor w poprzednim miejscu */ MBUTTONS SELECTDOWN;MBUTTONS SELECTUP /* "stempluj" brush */ I tak dalej... Pole do dziaîania otwarte. Skrypt ten dziaîa na ekranie 640 x 512 pod warunkiem, ûe tak jak poprzednio ma jakiô brush, narzëdzie do "kropkowania" i wîâczonâ opcjë COLOR. Czemu COLOR? Ano, jak damy MATTE, to dziesiëê razy wykonamy rozrzucanie takich samych brushy. Przy COLOR co drugi raz je lekko zepsujemy, poniewaû zadziaîajâ rozkazy zmiany koloru z 1 na 0 i odwrotnie. A o to wîaônie chodzi przy tworzeniu tekstur. Trzecia ilustracja pokazuje kilka takich tekstur przygotowanych z pomocâ opisanego skryptu. Moûna (i naleûy) zmieniê obszar rysowania. Natomiast udoskonalanie skryptu przez dodawanie kolejnych rozkazów jest juû doôê dyskusyjne. Opisane wyûej makro pozwala wybraê dowolny brush i po skoïczeniu pracy pozostawia nas z "surowcem" do tworzenia tekstury. Jak widaê, rodzaje takich tekstur mogâ byê bardzo zróûnicowane. Im bardziej rozbudowany bëdzie skrypt, tym mniejsza bëdzie moûliwoôê modyfikacji koïcowego efektu z poziomu Deluxa. Nie pokazaîem tego, ale byê moûe celowe byîoby uzupeînienie skryptu o opcjë rozmazywania. Moûna to osiâgnâê przez dodanie polecenia wyciëcia fragmentu stworzonego obrazu (paska) i przeciâgniëcie go opcjâ SMEAR przez rysunek. Najbardziej jednak sensownâ modyfikacjâ (rozmazywanie moûna wykonaê "rëcznie") jest staranne dobranie parametrów losowania oraz ksztaîtu samego brusha do malowania. Poniewaû, jak wspomniaîem, losowanie nie jest doskonaîe, pole obrazu jest zagëszczone w ôrodkowej czëôci i nieco wydîuûone w pionie. Odpowiednie dobranie brusha -- okrâgîa plamka, kwadracik, pasek lub skrëcona nitka -- decyduje o koïcowym efekcie. Jednym z pierwszych skryptów, który wykonaîem "z koniecznoôci", byî skrypt do wycinania brushy z ekranu. Powód byî taki: przygotowywaîem zestaw ikon (do menu) komercyjnego programu. Tego typu praca jest na ogóî wielokrotnie wykonywana. Ikony trzeba ciâgle poprawiaê, zmieniajâ sië ich nazwy, kolejnoôê, kolory i tak dalej. Najlepiej w takim wypadku wykonaê serië obrazków na ekranie programu malarskiego. Obrazki sâ jednakowej wielkoôci, uîoûone zwykle w prostokât liniami i kolumnami. W ten sposób moûna îatwo wyciâê z obrazu odpowiednie brushe ikon. Îatwo teû sprawdzaê ich czytelnoôê róûnymi paletami. Wyciëte brushe zamieniamy na IFF bez kompresji, np. programikiem IFFtoILBM. Koder zamieni to z kolei na jëzyk C lub asembler. Problem leûy jednak w nazwach ikon. Majâc takich obrazków do wykonania dwadzieôcia lub piëêdziesiât nie wiemy, jak który sië nazywa. Pisanie nazw przy rysunku nie pozwala na uîoûenie ich w zwarty blok gotowy do pociëcia na fragmenty. Przygotowujemy na rysunku blok ikon (brushy do wyciëcia), a do skryptu poza wymiarami obszaru do wyciëcia umieszczamy kolejno potrzebne nazwy. Moûemy teraz dowolnie poprawiaê wyglâd ikon na wspólnym obrazku, a program i tak wytnie automatycznie odpowiednie brushe, nada im ustalone wczeôniej nazwy i zapisze je w odpowiednim miejscu. W przeciwnym wypadku zmuszeni jesteômy do wykonywania "rëcznej" roboty wycinania i ciâgîego sprawdzania, czy brush zapisujemy pod ustalonâ uprzednio nazwâ. Przy kilkudziesiëciu ikonach jest to powaûny problem. Skrypt zaczynamy tradycyjnym nagîówkiem z dodatkami, po czym wpisujemy odpowiednie nazwy dla kolejnych brushy, ze ôcieûkâ do miejsca zapisania: a$.1="dh1:temp/Zaîaduj_plik.iff" /* 1 komórka tablicy z pierwszâ nazwâ brusha i ôcieûkâ */ a$.2="dh1:temp/Zapisz_plik.iff" /* 2 komórka tablicy z drugâ nazwâ brusha i ôcieûkâ */ a$.n="dh1:temp/Pomoc.iff" /* n-ta komórka tablicy z n-tâ nazwâ brusha i ôcieûkâ */ WIER=w;KOL=k /* iloôê wierszy =w, kolumn =k */ Xn=x;Yn=y /* parametry górnego, lewego naroûnika bloku =x, y */ BX=x1;BY=y1 /* wielkoôê pojedynczego brusha szer=x1, wysok=y1 */ YY=Yn-BY;numer=0 DO i=1 TO WIER;XX=Xn-BX;YY=YY+BY /* kolejne wiersze */ DO j=1 TO KOL;XX=XX+BX /* kolejne kolumny */ BRUSH XX YY BX-1 BY-1 CUT;SOLIDBODY ON /* wytnij brush jako REPLIC */ numer=numer+1 /* ustaw numer brusha */ SAVEBRUSH a$.numer /* zapisz wyciëty brush w sposób podany w tablicy a$.numer */ END;END /* koniec pëtli */ PANEL ON;TITLE ON;FREEBRUSH;UNLOCKGUI;EXIT /* przywróê panel, uwolnij brush i skoïcz */ Oczywiôcie liczba wierszy bloku brushy razy liczba kolumn powinna odpowiadaê liczbie nazw, pod jakimi zapiszemy brushe. Jeûeli jednak blok ikon jest nierównomierny, tj. wycinamy wiëcej maîych brushy niû potrzeba nam ikon, to nie jest to ûaden kîopot. I tak póúniej przenosimy je z przykîadowo podanego katalogu Temp do wîaôciwego katalogu, np. "Brushe_do MUI", "Brushe_dwukolorowe" itd. Rzecz jasna, nazw, czyli komórek tablicy "a$", nie powinno byê mniej, bo program nie bëdzie wiedziaî, gdzie co zapisaê i GURU gotowe. Makra do Deluxe Paint nie zastâpiâ nam normalnej pracy, ale mogâ jâ bardzo uîatwiê. Ciekawe, ûe jakoô nikt sië w to dotychczas nie bawiî. Nie znalazîem w Aminecie ani jednego skryptu do naszego programu. Naleûy jednak pamiëtaê, ûe najbardziej naturalnâ funkcjâ makra w Deluxe Paint jest zapisanie i powtórzenie ostatnio wykonywanych czynnoôci. Takâ moûliwoôê miaî kiedyô DigiPaint III. Kto go jeszcze uûywa? *Donald Hearn, M. Pauline Baker "Grafika Mikrokomputerowa", str. 90, WNT Warszawa 1988 r.